diff options
author | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-01-21 20:52:44 +0000 |
---|---|---|
committer | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-01-21 20:52:44 +0000 |
commit | 427d3c76bf451543bb5734df43e3dc6b703afc19 (patch) | |
tree | b346c633f75c76e38b841d3081fc309025372972 /gcc/stmt.c | |
parent | cb440058716b6cb82798fe7c5f412774a19fd766 (diff) | |
download | gcc-427d3c76bf451543bb5734df43e3dc6b703afc19.tar.gz |
* stmt.c (same_case_target_p): New function to determine whether
two case labels branch to the same target. Split out from...
(group_case_nodes): ... here. Use same_case_target_p instead.
(strip_default_case_nodes): Remove explicit case nodes
that branch to the default destination.
(expand_end_case_type): Call strip_default_case_nodes after
group_case_nodes, to simplify the case-list before we count it.
Only generate table_label RTX when actually needed. Try to share
thiscase->exit_label and thiscase->data.case_stmt.default_label
when a switch has no explicit default case. Simplify test for
constant index.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@61570 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/stmt.c')
-rw-r--r-- | gcc/stmt.c | 78 |
1 files changed, 65 insertions, 13 deletions
diff --git a/gcc/stmt.c b/gcc/stmt.c index b6503cfa9ca..043b752cb45 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -418,6 +418,8 @@ static void expand_cleanups PARAMS ((tree, tree, int, int)); static void check_seenlabel PARAMS ((void)); static void do_jump_if_equal PARAMS ((rtx, rtx, rtx, int)); static int estimate_case_costs PARAMS ((case_node_ptr)); +static bool same_case_target_p PARAMS ((rtx, rtx)); +static void strip_default_case_nodes PARAMS ((case_node_ptr *, rtx)); static void group_case_nodes PARAMS ((case_node_ptr)); static void balance_case_nodes PARAMS ((case_node_ptr *, case_node_ptr)); @@ -5201,13 +5203,13 @@ expand_end_case_type (orig_index, orig_type) rtx before_case, end; struct nesting *thiscase = case_stack; tree index_expr, index_type; + bool exit_done = false; int unsignedp; /* Don't crash due to previous errors. */ if (thiscase == NULL) return; - table_label = gen_label_rtx (); index_expr = thiscase->data.case_stmt.index_expr; index_type = TREE_TYPE (index_expr); unsignedp = TREE_UNSIGNED (index_type); @@ -5247,6 +5249,13 @@ expand_end_case_type (orig_index, orig_type) { thiscase->data.case_stmt.default_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); + /* Share the exit label if possible. */ + if (thiscase->exit_label) + { + SET_DECL_RTL (thiscase->data.case_stmt.default_label, + thiscase->exit_label); + exit_done = true; + } expand_label (thiscase->data.case_stmt.default_label); } default_label = label_rtx (thiscase->data.case_stmt.default_label); @@ -5260,6 +5269,8 @@ expand_end_case_type (orig_index, orig_type) /* Simplify the case-list before we count it. */ group_case_nodes (thiscase->data.case_stmt.case_list); + strip_default_case_nodes (&thiscase->data.case_stmt.case_list, + default_label); /* Get upper and lower bounds of case values. Also convert all the case values to the index expr's data type. */ @@ -5321,9 +5332,7 @@ expand_end_case_type (orig_index, orig_type) #ifndef ASM_OUTPUT_ADDR_DIFF_ELT || flag_pic #endif - || TREE_CODE (index_expr) == INTEGER_CST - || (TREE_CODE (index_expr) == COMPOUND_EXPR - && TREE_CODE (TREE_OPERAND (index_expr, 1)) == INTEGER_CST)) + || TREE_CONSTANT (index_expr)) { index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0); @@ -5406,6 +5415,7 @@ expand_end_case_type (orig_index, orig_type) } else { + table_label = gen_label_rtx (); if (! try_casesi (index_type, index_expr, minval, range, table_label, default_label)) { @@ -5487,7 +5497,7 @@ expand_end_case_type (orig_index, orig_type) else end_cleanup_deferral (); - if (thiscase->exit_label) + if (thiscase->exit_label && !exit_done) emit_label (thiscase->exit_label); POPSTACK (case_stack); @@ -5617,6 +5627,54 @@ estimate_case_costs (node) return 1; } +/* Determine whether two case labels branch to the same target. */ + +static bool +same_case_target_p (l1, l2) + rtx l1, l2; +{ + rtx i1, i2; + + if (l1 == l2) + return true; + + i1 = next_real_insn (l1); + i2 = next_real_insn (l2); + if (i1 == i2) + return true; + + if (i1 && simplejump_p (i1)) + { + l1 = XEXP (SET_SRC (PATTERN (i1)), 0); + } + + if (i2 && simplejump_p (i2)) + { + l2 = XEXP (SET_SRC (PATTERN (i2)), 0); + } + return l1 == l2; +} + +/* Delete nodes that branch to the default label from a list of + case nodes. Eg. case 5: default: becomes just default: */ + +static void +strip_default_case_nodes (prev, deflab) + case_node_ptr *prev; + rtx deflab; +{ + case_node_ptr ptr; + + while (*prev) + { + ptr = *prev; + if (same_case_target_p (label_rtx (ptr->code_label), deflab)) + *prev = ptr->right; + else + prev = &ptr->right; + } +} + /* Scan an ordered list of case nodes combining those with consecutive values or ranges. @@ -5630,19 +5688,13 @@ group_case_nodes (head) while (node) { - rtx lb = next_real_insn (label_rtx (node->code_label)); - rtx lb2; + rtx lab = label_rtx (node->code_label); case_node_ptr np = node; /* Try to group the successors of NODE with NODE. */ while (((np = np->right) != 0) /* Do they jump to the same place? */ - && ((lb2 = next_real_insn (label_rtx (np->code_label))) == lb - || (lb != 0 && lb2 != 0 - && simplejump_p (lb) - && simplejump_p (lb2) - && rtx_equal_p (SET_SRC (PATTERN (lb)), - SET_SRC (PATTERN (lb2))))) + && same_case_target_p (label_rtx (np->code_label), lab) /* Are their ranges consecutive? */ && tree_int_cst_equal (np->low, fold (build (PLUS_EXPR, |