Commit b7d8d447 by Rafael Avila de Espindola Committed by Rafael Espindola

tree-vrp.c (find_case_label_index): Fix the binary search.

2008-04-18  Rafael Espindola  <espindola@google.com>
	* tree-vrp.c (find_case_label_index): Fix the binary search.
	(find_case_label_range): New.
	(vrp_visit_switch_stmt): Use find_case_label_range.
	(simplify_switch_using_ranges): Use find_case_label_range.

From-SVN: r134452
parent 0ce7db60
2008-04-18 Rafael Espindola <espindola@google.com>
* tree-vrp.c (find_case_label_index): Fix the binary search.
(find_case_label_range): New.
(vrp_visit_switch_stmt): Use find_case_label_range.
(simplify_switch_using_ranges): Use find_case_label_range.
2008-04-18 Eric Botcazou <ebotcazou@adacore.com> 2008-04-18 Eric Botcazou <ebotcazou@adacore.com>
* gimplify.c (gimplify_modify_expr_rhs) <COND_EXPR>: Gimplify the LHS * gimplify.c (gimplify_modify_expr_rhs) <COND_EXPR>: Gimplify the LHS
......
...@@ -5528,48 +5528,52 @@ vrp_visit_cond_stmt (tree stmt, edge *taken_edge_p) ...@@ -5528,48 +5528,52 @@ vrp_visit_cond_stmt (tree stmt, edge *taken_edge_p)
return (*taken_edge_p) ? SSA_PROP_INTERESTING : SSA_PROP_VARYING; return (*taken_edge_p) ? SSA_PROP_INTERESTING : SSA_PROP_VARYING;
} }
/* Searches the case label vector VEC for the index *IDX of the CASE_LABEL
that includes the value VAL. The search is restricted to the range
[START_IDX, n - 2] where n is the size of VEC (n - 1 is the default label).
/* Searches the case label vector VEC for the index *IDX the CASE_LABEL If there is a CASE_LABEL for VAL, its index is placed in IDX and true is
includes the value VAL. The search starts at index START_IDX and returned.
true is returned if *IDX corresponds to such an index. False is
returned in case VAL hits the default case label and *IDX in this If there is no CASE_LABEL for VAL and the is one that is larger than VAL,
case is the next higher or the next lower case label index. */ it is placed in IDX and false is returned.
If VAL is larger than any CASE_LABEL, n - 1 is placed on IDX and false is
returned. */
static bool static bool
find_case_label_index (tree vec, size_t start_idx, tree val, size_t *idx) find_case_label_index (tree vec, size_t start_idx, tree val, size_t *idx)
{ {
size_t n = TREE_VEC_LENGTH (vec); size_t n = TREE_VEC_LENGTH (vec);
size_t low, high, i = start_idx; size_t low, high;
/* Find case label for minimum of the value range or the next one.
At each iteration we are searching in [low, high - 1]. */
/* Find case label for minimum of the value range or the next one. */ for (low = start_idx, high = n - 1; high != low; )
for (low = start_idx - 1, high = n - 1; high - low > 1; )
{ {
tree t; tree t;
int cmp; int cmp;
i = (high + low) / 2; /* Note that i != high, so we never ask for n - 1. */
size_t i = (high + low) / 2;
t = TREE_VEC_ELT (vec, i); t = TREE_VEC_ELT (vec, i);
/* Cache the result of comparing CASE_LOW and val. */ /* Cache the result of comparing CASE_LOW and val. */
cmp = tree_int_cst_compare (CASE_LOW (t), val); cmp = tree_int_cst_compare (CASE_LOW (t), val);
if (cmp > 0) if (cmp == 0)
{
/* Ranges cannot be empty. */
*idx = i;
return true;
}
else if (cmp > 0)
high = i; high = i;
else else
low = i; {
low = i + 1;
if (CASE_HIGH (t) == NULL) if (CASE_HIGH (t) != NULL
{ && tree_int_cst_compare (CASE_HIGH (t), val) >= 0)
/* A singe-valued case label. */
if (cmp == 0)
{
*idx = i;
return true;
}
}
else
{
/* A case range. We can only handle integer ranges. */
if (cmp <= 0 && tree_int_cst_compare (CASE_HIGH (t), val) >= 0)
{ {
*idx = i; *idx = i;
return true; return true;
...@@ -5577,10 +5581,66 @@ find_case_label_index (tree vec, size_t start_idx, tree val, size_t *idx) ...@@ -5577,10 +5581,66 @@ find_case_label_index (tree vec, size_t start_idx, tree val, size_t *idx)
} }
} }
*idx = i; *idx = high;
return false; return false;
} }
/* Searches the case label vector VEC for the range of CASE_LABELs that is used
for values between MIN and MAX. The first index is placed in MIN_IDX. The
last index is placed in MAX_IDX. If the range of CASE_LABELs is empty
then MAX_IDX < MIN_IDX.
Returns true if the default label is not needed. */
static bool
find_case_label_range (tree vec, tree min, tree max, size_t *min_idx, size_t *max_idx)
{
size_t i, j;
bool min_take_default = !find_case_label_index (vec, 0, min, &i);
bool max_take_default = !find_case_label_index (vec, i, max, &j);
if (i == j
&& min_take_default
&& max_take_default)
{
/* Only the default case label reached.
Return an empty range. */
*min_idx = 1;
*max_idx = 0;
return false;
}
else
{
bool take_default = min_take_default || max_take_default;
tree low, high;
size_t k;
if (max_take_default)
j--;
/* If the case label range is continuous, we do not need
the default case label. Verify that. */
high = CASE_LOW (TREE_VEC_ELT (vec, i));
if (CASE_HIGH (TREE_VEC_ELT (vec, i)))
high = CASE_HIGH (TREE_VEC_ELT (vec, i));
for (k = i + 1; k <= j; ++k)
{
low = CASE_LOW (TREE_VEC_ELT (vec, k));
if (!integer_onep (int_const_binop (MINUS_EXPR, low, high, 0)))
{
take_default = true;
break;
}
high = low;
if (CASE_HIGH (TREE_VEC_ELT (vec, k)))
high = CASE_HIGH (TREE_VEC_ELT (vec, k));
}
*min_idx = i;
*max_idx = j;
return !take_default;
}
}
/* Visit switch statement STMT. If we can determine which edge /* Visit switch statement STMT. If we can determine which edge
will be taken out of STMT's basic block, record it in will be taken out of STMT's basic block, record it in
*TAKEN_EDGE_P and return SSA_PROP_INTERESTING. Otherwise, return *TAKEN_EDGE_P and return SSA_PROP_INTERESTING. Otherwise, return
...@@ -5593,7 +5653,7 @@ vrp_visit_switch_stmt (tree stmt, edge *taken_edge_p) ...@@ -5593,7 +5653,7 @@ vrp_visit_switch_stmt (tree stmt, edge *taken_edge_p)
value_range_t *vr; value_range_t *vr;
size_t i = 0, j = 0, n; size_t i = 0, j = 0, n;
tree vec; tree vec;
bool min_take_default, max_take_default; bool take_default;
*taken_edge_p = NULL; *taken_edge_p = NULL;
op = TREE_OPERAND (stmt, 0); op = TREE_OPERAND (stmt, 0);
...@@ -5618,27 +5678,23 @@ vrp_visit_switch_stmt (tree stmt, edge *taken_edge_p) ...@@ -5618,27 +5678,23 @@ vrp_visit_switch_stmt (tree stmt, edge *taken_edge_p)
vec = SWITCH_LABELS (stmt); vec = SWITCH_LABELS (stmt);
n = TREE_VEC_LENGTH (vec); n = TREE_VEC_LENGTH (vec);
/* Find case label for minimum of the value range or the next one. */ take_default = !find_case_label_range (vec, vr->min, vr->max, &i, &j);
min_take_default = !find_case_label_index (vec, 0, vr->min, &i);
/* Find case label for maximum of the value range or the previous one. */
max_take_default = !find_case_label_index (vec, i, vr->max, &j);
/* Check if we reach the default label only. */ /* Check if the range spans no CASE_LABEL. If so, we only reach the default
label */
if (j < i) if (j < i)
val = TREE_VEC_ELT (vec, n - 1); {
/* Check if we reach exactly one label and not the default label. */ gcc_assert (take_default);
else if (i == j val = TREE_VEC_ELT (vec, n - 1);
&& !min_take_default }
&& !max_take_default)
val = TREE_VEC_ELT (vec, i);
else else
{ {
/* Check if labels with index i to j are all reaching the same label. /* Check if labels with index i to j and maybe the default label
If we don't hit a single case label only, the default case also has are all reaching the same label. */
to branch to the same label. */
val = TREE_VEC_ELT (vec, i); val = TREE_VEC_ELT (vec, i);
if (CASE_LABEL (TREE_VEC_ELT (vec, n - 1)) != CASE_LABEL (val)) if (take_default
&& CASE_LABEL (TREE_VEC_ELT (vec, n - 1)) != CASE_LABEL (val))
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " not a single destination for this " fprintf (dump_file, " not a single destination for this "
...@@ -6323,32 +6379,7 @@ simplify_switch_using_ranges (tree stmt) ...@@ -6323,32 +6379,7 @@ simplify_switch_using_ranges (tree stmt)
/* Find case label for min/max of the value range. */ /* Find case label for min/max of the value range. */
vec = SWITCH_LABELS (stmt); vec = SWITCH_LABELS (stmt);
n = TREE_VEC_LENGTH (vec); n = TREE_VEC_LENGTH (vec);
take_default = !find_case_label_index (vec, 0, vr->min, &i); take_default = !find_case_label_range (vec, vr->min, vr->max, &i, &j);
take_default |= !find_case_label_index (vec, i, vr->max, &j);
/* If the case label range is continuous, we do not need to
preserve the default case label. Verify that. */
if (!take_default && j > i)
{
tree low, high;
size_t k;
high = CASE_LOW (TREE_VEC_ELT (vec, i));
if (CASE_HIGH (TREE_VEC_ELT (vec, i)))
high = CASE_HIGH (TREE_VEC_ELT (vec, i));
for (k = i + 1; k <= j; ++k)
{
low = CASE_LOW (TREE_VEC_ELT (vec, k));
if (!integer_onep (int_const_binop (MINUS_EXPR, low, high, 0)))
{
take_default = true;
break;
}
high = low;
if (CASE_HIGH (TREE_VEC_ELT (vec, k)))
high = CASE_HIGH (TREE_VEC_ELT (vec, k));
}
}
/* Bail out if this is just all edges taken. */ /* Bail out if this is just all edges taken. */
if (i == 0 if (i == 0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment