From 0dfa7ba12c7cbdfc177b07f990a859761dc36e25 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Thu, 25 Jul 2019 16:16:32 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 5 ++ gcc/stmt.c | 57 +++++++++++++------- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gnat.dg/case_optimization3.adb | 25 +++++++++ gcc/testsuite/gnat.dg/case_optimization3.ads | 10 ++++ 5 files changed, 83 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/case_optimization3.adb create mode 100644 gcc/testsuite/gnat.dg/case_optimization3.ads diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4196db249da..336e9eef2c3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-25 Eric Botcazou + + * stmt.c (expand_case): Try to narrow the index type if it's larger + than a word. Tidy up. + 2019-07-25 Eric Botcazou * cif-code.def (NEVER_CALL): New code. diff --git a/gcc/stmt.c b/gcc/stmt.c index 040899e2731..17f43d14d88 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -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 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 4dad677d41d..948acc0c771 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-25 Eric Botcazou + + * gnat.dg/case_optimization3.ad[sb]: New test. + 2019-07-25 Martin Liska diff --git a/gcc/testsuite/gnat.dg/case_optimization3.adb b/gcc/testsuite/gnat.dg/case_optimization3.adb new file mode 100644 index 00000000000..6887f325d4d --- /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 00000000000..3e3c769c2f5 --- /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; -- 2.30.2