aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2019-07-25 16:16:32 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2019-07-25 16:16:32 +0000
commit0dfa7ba12c7cbdfc177b07f990a859761dc36e25 (patch)
tree90a092de84a26f643015a197a2e32ad6ed8bf2e2 /gcc
parent5ab2422adf894bdf84deed8c7c0557c16d6dca2b (diff)
downloadgcc-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/ChangeLog5
-rw-r--r--gcc/stmt.c57
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gnat.dg/case_optimization3.adb25
-rw-r--r--gcc/testsuite/gnat.dg/case_optimization3.ads10
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.
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 040899e..17f43d1 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<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;