Commit 5720c7e7 by Richard Kenner

(check_for_full_enumeration_handling): Call case_tree2list before checking for...

(check_for_full_enumeration_handling): Call case_tree2list
before checking for case expressions not corresponding to enumerators.
(mark_seen_cases): If SPARSENESS == 2, exploit AVL order.
Else, convert tree to list.
Set xlo to -1 if SPARSENESS == 1 search failed.
(expand_end_case): Avoid calling case_tree2list on list.

From-SVN: r11857
parent b059139c
...@@ -143,8 +143,9 @@ extern void (*interim_eh_hook) PROTO((tree)); ...@@ -143,8 +143,9 @@ extern void (*interim_eh_hook) PROTO((tree));
statements. We handle "range" labels; for a single-value label statements. We handle "range" labels; for a single-value label
as in C, the high and low limits are the same. as in C, the high and low limits are the same.
A chain of case nodes is initially maintained via the RIGHT fields An AVL tree of case nodes is initially created, and later transformed
in the nodes. Nodes with higher case values are later in the list. to a list linked via the RIGHT fields in the nodes. Nodes with
higher case values are later in the list.
Switch statements can be output in one of two forms. A branch table Switch statements can be output in one of two forms. A branch table
is used if there are more than a few labels and the labels are dense is used if there are more than a few labels and the labels are dense
...@@ -4280,6 +4281,8 @@ add_case_node (low, high, label, duplicate) ...@@ -4280,6 +4281,8 @@ add_case_node (low, high, label, duplicate)
else else
/* r->balance == +1 */ /* r->balance == +1 */
{ {
/* LR-Rotation */
int b2; int b2;
struct case_node *t = r->right; struct case_node *t = r->right;
...@@ -4570,36 +4573,62 @@ mark_seen_cases (type, cases_seen, count, sparseness) ...@@ -4570,36 +4573,62 @@ mark_seen_cases (type, cases_seen, count, sparseness)
tree next_node_to_try = NULL_TREE; tree next_node_to_try = NULL_TREE;
long next_node_offset = 0; long next_node_offset = 0;
register struct case_node *n; register struct case_node *n, *root = case_stack->data.case_stmt.case_list;
tree val = make_node (INTEGER_CST); tree val = make_node (INTEGER_CST);
TREE_TYPE (val) = type; TREE_TYPE (val) = type;
for (n = case_stack->data.case_stmt.case_list; n; if (! root)
n = n->right) ; /* Do nothing */
else if (sparseness == 2)
{ {
TREE_INT_CST_LOW (val) = TREE_INT_CST_LOW (n->low); tree t;
TREE_INT_CST_HIGH (val) = TREE_INT_CST_HIGH (n->low); HOST_WIDE_INT xlo;
while ( ! tree_int_cst_lt (n->high, val))
/* This less efficient loop is only needed to handle
duplicate case values (multiple enum constants
with the same value). */
TREE_TYPE (val) = TREE_TYPE (root->low);
for (t = TYPE_VALUES (type), xlo = 0; t != NULL_TREE;
t = TREE_CHAIN (t), xlo++)
{ {
/* Calculate (into xlo) the "offset" of the integer (val). TREE_INT_CST_LOW (val) = TREE_INT_CST_LOW (TREE_VALUE (t));
The element with lowest value has offset 0, the next smallest TREE_INT_CST_HIGH (val) = TREE_INT_CST_HIGH (TREE_VALUE (t));
element has offset 1, etc. */ n = root;
do
HOST_WIDE_INT xlo, xhi;
tree t;
if (sparseness == 2)
{ {
/* This less efficient loop is only needed to handle /* Keep going past elements distinctly greater than VAL. */
duplicate case values (multiple enum constants if (tree_int_cst_lt (val, n->low))
with the same value). */ n = n->left;
for (t = TYPE_VALUES (type), xlo = 0; t != NULL_TREE;
t = TREE_CHAIN (t), xlo++) /* or distinctly less than VAL. */
else if (tree_int_cst_lt (n->high, val))
n = n->right;
else
{ {
if (tree_int_cst_equal (val, TREE_VALUE (t))) /* We have found a matching range. */
BITARRAY_SET (cases_seen, xlo); BITARRAY_SET (cases_seen, xlo);
break;
} }
} }
else while (n);
}
}
else
{
if (root->left)
case_stack->data.case_stmt.case_list = root = case_tree2list (root, 0);
for (n = root; n; n = n->right)
{
TREE_INT_CST_LOW (val) = TREE_INT_CST_LOW (n->low);
TREE_INT_CST_HIGH (val) = TREE_INT_CST_HIGH (n->low);
while ( ! tree_int_cst_lt (n->high, val))
{ {
/* Calculate (into xlo) the "offset" of the integer (val).
The element with lowest value has offset 0, the next smallest
element has offset 1, etc. */
HOST_WIDE_INT xlo, xhi;
tree t;
if (sparseness && TYPE_VALUES (type) != NULL_TREE) if (sparseness && TYPE_VALUES (type) != NULL_TREE)
{ {
/* The TYPE_VALUES will be in increasing order, so /* The TYPE_VALUES will be in increasing order, so
...@@ -4623,7 +4652,10 @@ mark_seen_cases (type, cases_seen, count, sparseness) ...@@ -4623,7 +4652,10 @@ mark_seen_cases (type, cases_seen, count, sparseness)
xlo++; xlo++;
t = TREE_CHAIN (t); t = TREE_CHAIN (t);
if (t == next_node_to_try) if (t == next_node_to_try)
break; {
xlo = -1;
break;
}
} }
} }
else else
...@@ -4641,10 +4673,10 @@ mark_seen_cases (type, cases_seen, count, sparseness) ...@@ -4641,10 +4673,10 @@ mark_seen_cases (type, cases_seen, count, sparseness)
if (xhi == 0 && xlo >= 0 && xlo < count) if (xhi == 0 && xlo >= 0 && xlo < count)
BITARRAY_SET (cases_seen, xlo); BITARRAY_SET (cases_seen, xlo);
add_double (TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val),
1, 0,
&TREE_INT_CST_LOW (val), &TREE_INT_CST_HIGH (val));
} }
add_double (TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val),
1, 0,
&TREE_INT_CST_LOW (val), &TREE_INT_CST_HIGH (val));
} }
} }
} }
...@@ -4706,7 +4738,7 @@ check_for_full_enumeration_handling (type) ...@@ -4706,7 +4738,7 @@ check_for_full_enumeration_handling (type)
/* The time complexity of this code is normally O(N), where /* The time complexity of this code is normally O(N), where
N being the number of members in the enumerated type. N being the number of members in the enumerated type.
However, if type is a ENUMERAL_TYPE whose values do not However, if type is a ENUMERAL_TYPE whose values do not
increase monotonically, quadratic time may be needed. */ increase monotonically, O(N*log(N)) time may be needed. */
mark_seen_cases (type, cases_seen, size, sparseness); mark_seen_cases (type, cases_seen, size, sparseness);
...@@ -4725,6 +4757,10 @@ check_for_full_enumeration_handling (type) ...@@ -4725,6 +4757,10 @@ check_for_full_enumeration_handling (type)
occur since C and C++ don't enforce type-checking of occur since C and C++ don't enforce type-checking of
assignments to enumeration variables. */ assignments to enumeration variables. */
if (case_stack->data.case_stmt.case_list
&& case_stack->data.case_stmt.case_list->left)
case_stack->data.case_stmt.case_list
= case_tree2list (case_stack->data.case_stmt.case_list, 0);
if (warn_switch) if (warn_switch)
for (n = case_stack->data.case_stmt.case_list; n; n = n->right) for (n = case_stack->data.case_stmt.case_list; n; n = n->right)
{ {
...@@ -4908,7 +4944,8 @@ expand_end_case (orig_index) ...@@ -4908,7 +4944,8 @@ expand_end_case (orig_index)
before_case = get_last_insn (); before_case = get_last_insn ();
if (thiscase->data.case_stmt.case_list) if (thiscase->data.case_stmt.case_list
&& thiscase->data.case_stmt.case_list->left)
thiscase->data.case_stmt.case_list thiscase->data.case_stmt.case_list
= case_tree2list(thiscase->data.case_stmt.case_list, 0); = case_tree2list(thiscase->data.case_stmt.case_list, 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