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
This commit is contained in:
Eric Botcazou 2019-07-25 16:16:32 +00:00 committed by Eric Botcazou
parent 5ab2422adf
commit 0dfa7ba12c
5 changed files with 83 additions and 18 deletions

View file

@ -1,3 +1,8 @@
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.

View file

@ -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 ();

View file

@ -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>

View file

@ -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" } }

View file

@ -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;