diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2019-07-25 16:16:32 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2019-07-25 16:16:32 +0000 |
commit | 0dfa7ba12c7cbdfc177b07f990a859761dc36e25 (patch) | |
tree | 90a092de84a26f643015a197a2e32ad6ed8bf2e2 /gcc/stmt.c | |
parent | 5ab2422adf894bdf84deed8c7c0557c16d6dca2b (diff) | |
download | gcc-0dfa7ba12c7cbdfc177b07f990a859761dc36e25.zip gcc-0dfa7ba12c7cbdfc177b07f990a859761dc36e25.tar.gz gcc-0dfa7ba12c7cbdfc177b07f990a859761dc36e25.tar.bz2 |
stmt.c (expand_case): Try to narrow the index type if it's larger than a word.
* stmt.c (expand_case): Try to narrow the index type if it's larger
than a word. Tidy up.
From-SVN: r273805
Diffstat (limited to 'gcc/stmt.c')
-rw-r--r-- | gcc/stmt.c | 57 |
1 files changed, 39 insertions, 18 deletions
@@ -885,6 +885,7 @@ expand_case (gswitch *stmt) tree index_type = TREE_TYPE (index_expr); tree elt; basic_block bb = gimple_bb (stmt); + gimple *def_stmt; auto_vec<simple_case_node> case_list; @@ -918,6 +919,31 @@ expand_case (gswitch *stmt) else maxval = fold_convert (index_type, CASE_LOW (elt)); + /* Try to narrow the index type if it's larger than a word. + That is mainly for -O0 where an equivalent optimization + done by forward propagation is not run and is aimed at + avoiding a call to a comparison routine of libgcc. */ + if (TYPE_PRECISION (index_type) > BITS_PER_WORD + && TREE_CODE (index_expr) == SSA_NAME + && (def_stmt = SSA_NAME_DEF_STMT (index_expr)) + && is_gimple_assign (def_stmt) + && gimple_assign_rhs_code (def_stmt) == NOP_EXPR) + { + tree inner_index_expr = gimple_assign_rhs1 (def_stmt); + tree inner_index_type = TREE_TYPE (inner_index_expr); + + if (INTEGRAL_TYPE_P (inner_index_type) + && TYPE_PRECISION (inner_index_type) <= BITS_PER_WORD + && int_fits_type_p (minval, inner_index_type) + && int_fits_type_p (maxval, inner_index_type)) + { + index_expr = inner_index_expr; + index_type = inner_index_type; + minval = fold_convert (index_type, minval); + maxval = fold_convert (index_type, maxval); + } + } + /* Compute span of values. */ range = fold_build2 (MINUS_EXPR, index_type, maxval, minval); @@ -969,27 +995,22 @@ expand_case (gswitch *stmt) rtx_insn *before_case = get_last_insn (); - /* Decide how to expand this switch. - The two options at this point are a dispatch table (casesi or - tablejump) or a decision tree. */ - + /* If the default case is unreachable, then set default_label to NULL + so that we omit the range check when generating the dispatch table. + We also remove the edge to the unreachable default case. The block + itself will be automatically removed later. */ + if (EDGE_COUNT (default_edge->dest->succs) == 0 + && gimple_seq_unreachable_p (bb_seq (default_edge->dest))) { - /* If the default case is unreachable, then set default_label to NULL - so that we omit the range check when generating the dispatch table. - We also remove the edge to the unreachable default case. The block - itself will be automatically removed later. */ - if (EDGE_COUNT (default_edge->dest->succs) == 0 - && gimple_seq_unreachable_p (bb_seq (default_edge->dest))) - { - default_label = NULL; - remove_edge (default_edge); - default_edge = NULL; - } - emit_case_dispatch_table (index_expr, index_type, - case_list, default_label, default_edge, - minval, maxval, range, bb); + default_label = NULL; + remove_edge (default_edge); + default_edge = NULL; } + emit_case_dispatch_table (index_expr, index_type, + case_list, default_label, default_edge, + minval, maxval, range, bb); + reorder_insns (NEXT_INSN (before_case), get_last_insn (), before_case); free_temp_slots (); |