diff options
author | Steven Bosscher <stevenb@suse.de> | 2004-05-26 22:36:49 +0000 |
---|---|---|
committer | Steven Bosscher <steven@gcc.gnu.org> | 2004-05-26 22:36:49 +0000 |
commit | f667741c42d3bc8082877638726e4d3a22285431 (patch) | |
tree | 9a721edcedc47294d0570c2ba52be9541243aeec /gcc/gimplify.c | |
parent | e4efa9715632519e202f57250b3d8954b17ac9c9 (diff) | |
download | gcc-f667741c42d3bc8082877638726e4d3a22285431.zip gcc-f667741c42d3bc8082877638726e4d3a22285431.tar.gz gcc-f667741c42d3bc8082877638726e4d3a22285431.tar.bz2 |
gimplify.c (compare_case_labels): New function.
* gimplify.c (compare_case_labels): New function.
(gimplify_switch_expr): Sort case labels, and make sure the
last label in the label vector is the default case.
* tree-cfg.c (group_case_labels): New function.
(build_tree_cfg): Cleanup redundant labels and group case labels
before creating edges.
(cleanup_dead_labels): Handle GOTO_EXPRs.
(find_case_label_for_value): Use a binary search to find the
case label for the given value.
* tree-gimple.c: Mention that labels are sorted, and that the
last label must be the default.
From-SVN: r82297
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r-- | gcc/gimplify.c | 50 |
1 files changed, 33 insertions, 17 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c index b081e5e..621569b 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -981,6 +981,19 @@ gimplify_loop_expr (tree *expr_p, tree *pre_p) return GS_ALL_DONE; } +/* Compare two case labels. Because the front end should already have + made sure that case ranges do not overlap, it is enough to only compare + the CASE_LOW values of each case label. */ + +static int +compare_case_labels (const void *p1, const void *p2) +{ + tree case1 = *(tree *)p1; + tree case2 = *(tree *)p2; + + return tree_int_cst_compare (CASE_LOW (case1), CASE_LOW (case2)); +} + /* Gimplify a SWITCH_EXPR, and collect a TREE_VEC of the labels it can branch to. */ @@ -996,8 +1009,7 @@ gimplify_switch_expr (tree *expr_p, tree *pre_p) if (SWITCH_BODY (switch_expr)) { varray_type labels, saved_labels; - bool saw_default; - tree label_vec, t; + tree label_vec, default_case = NULL_TREE; size_t i, len; /* If someone can be bothered to fill in the labels, they can @@ -1014,39 +1026,43 @@ gimplify_switch_expr (tree *expr_p, tree *pre_p) gimplify_ctxp->case_labels = saved_labels; len = VARRAY_ACTIVE_SIZE (labels); - saw_default = false; for (i = 0; i < len; ++i) { - t = VARRAY_TREE (labels, i); + tree t = VARRAY_TREE (labels, i); if (!CASE_LOW (t)) { - saw_default = true; + /* The default case must be the last label in the list. */ + default_case = t; + VARRAY_TREE (labels, i) = VARRAY_TREE (labels, len - 1); + len--; break; } } - label_vec = make_tree_vec (len + !saw_default); + label_vec = make_tree_vec (len + 1); SWITCH_LABELS (*expr_p) = label_vec; - - for (i = 0; i < len; ++i) - TREE_VEC_ELT (label_vec, i) = VARRAY_TREE (labels, i); - append_to_statement_list (switch_expr, pre_p); - /* If the switch has no default label, add one, so that we jump - around the switch body. */ - if (!saw_default) + if (! default_case) { - t = build (CASE_LABEL_EXPR, void_type_node, NULL_TREE, - NULL_TREE, create_artificial_label ()); - TREE_VEC_ELT (label_vec, len) = t; + /* If the switch has no default label, add one, so that we jump + around the switch body. */ + default_case = build (CASE_LABEL_EXPR, void_type_node, NULL_TREE, + NULL_TREE, create_artificial_label ()); append_to_statement_list (SWITCH_BODY (switch_expr), pre_p); - *expr_p = build (LABEL_EXPR, void_type_node, CASE_LABEL (t)); + *expr_p = build (LABEL_EXPR, void_type_node, + CASE_LABEL (default_case)); } else *expr_p = SWITCH_BODY (switch_expr); + qsort (&VARRAY_TREE (labels, 0), len, sizeof (tree), + compare_case_labels); + for (i = 0; i < len; ++i) + TREE_VEC_ELT (label_vec, i) = VARRAY_TREE (labels, i); + TREE_VEC_ELT (label_vec, len) = default_case; + SWITCH_BODY (switch_expr) = NULL; } else if (!SWITCH_LABELS (switch_expr)) |