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 | |
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')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/stmt.c | 57 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/case_optimization3.adb | 25 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/case_optimization3.ads | 10 |
5 files changed, 83 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4196db2..336e9ee 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,10 @@ 2019-07-25 Eric Botcazou <ebotcazou@adacore.com> + * stmt.c (expand_case): Try to narrow the index type if it's larger + than a word. Tidy up. + +2019-07-25 Eric Botcazou <ebotcazou@adacore.com> + * cif-code.def (NEVER_CALL): New code. * ipa-inline.c (want_inline_small_function_p): Fix formatting issues. Set the failure to CIF_NEVER_CALL if the IPA count is zero. @@ -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 (); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4dad677..948acc0c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-25 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/case_optimization3.ad[sb]: New test. + 2019-07-25 Martin Liska <mliska@suse.cz Dominik Infuhr <dominik.infuehr@theobroma-systems.com> diff --git a/gcc/testsuite/gnat.dg/case_optimization3.adb b/gcc/testsuite/gnat.dg/case_optimization3.adb new file mode 100644 index 0000000..6887f32 --- /dev/null +++ b/gcc/testsuite/gnat.dg/case_optimization3.adb @@ -0,0 +1,25 @@ +-- { dg-do compile } + +package body Case_Optimization3 is + + procedure Proc (Val : T_RANGE) is + begin + case Val is + when 0 => + raise Program_Error; + when 1 => + null; + when 2 => + null; + when 3 => + null; + when 4 => + null; + when others => + null; + end case; + end; + +end Case_Optimization3; + +-- { dg-final { scan-assembler-not "__ucmpdi2" } } diff --git a/gcc/testsuite/gnat.dg/case_optimization3.ads b/gcc/testsuite/gnat.dg/case_optimization3.ads new file mode 100644 index 0000000..3e3c769 --- /dev/null +++ b/gcc/testsuite/gnat.dg/case_optimization3.ads @@ -0,0 +1,10 @@ +package Case_Optimization3 is + + type T_UINT32 is range 0 .. (2 ** 32) - 1; + for T_UINT32'Size use 32; + + subtype T_RANGE is T_UINT32 range 0 .. 7; + + procedure Proc (Val : T_RANGE); + +end Case_Optimization3; |