diff options
author | Martin Liska <mliska@suse.cz> | 2018-06-28 09:14:57 +0200 |
---|---|---|
committer | Martin Liska <marxin@gcc.gnu.org> | 2018-06-28 07:14:57 +0000 |
commit | df7c79742af79bc2873ca28a8b3037a088444ca7 (patch) | |
tree | d5a6e4444e56568e59909022661c11a5e58bbaea /gcc/tree-switch-conversion.c | |
parent | d86c7648fb9643640d8c82be19d49927aa488768 (diff) | |
download | gcc-df7c79742af79bc2873ca28a8b3037a088444ca7.zip gcc-df7c79742af79bc2873ca28a8b3037a088444ca7.tar.gz gcc-df7c79742af79bc2873ca28a8b3037a088444ca7.tar.bz2 |
Fix clustering algorithm in switch expansion.
2018-06-28 Martin Liska <mliska@suse.cz>
* tree-switch-conversion.c (jump_table_cluster::find_jump_tables):
Add new checking assert to catch invalid state.
(jump_table_cluster::can_be_handled): Handle single case
clusters.
(jump_table_cluster::is_beneficial): Bail out for such case.
(bit_test_cluster::find_bit_tests):
Add new checking assert to catch invalid state.
(bit_test_cluster::can_be_handled): Handle single case
clusters.
(bit_test_cluster::is_beneficial): Bail out for such case.
(switch_decision_tree::analyze_switch_statement):
Fix comment.
2018-06-28 Martin Liska <mliska@suse.cz>
* gcc.dg/tree-ssa/switch-1.c: New test.
From-SVN: r262211
Diffstat (limited to 'gcc/tree-switch-conversion.c')
-rw-r--r-- | gcc/tree-switch-conversion.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c index 029ce8c..ddd8cba 100644 --- a/gcc/tree-switch-conversion.c +++ b/gcc/tree-switch-conversion.c @@ -1121,6 +1121,8 @@ jump_table_cluster::find_jump_tables (vec<cluster *> &clusters) && can_be_handled (clusters, j, i - 1)) min[i] = min_cluster_item (min[j].m_count + 1, j, s); } + + gcc_checking_assert (min[i].m_count != INT_MAX); } /* No result. */ @@ -1172,8 +1174,13 @@ jump_table_cluster::can_be_handled (const vec<cluster *> &clusters, if (!flag_jump_tables) return false; - unsigned HOST_WIDE_INT max_ratio = optimize_insn_for_size_p () ? 3 : 8; + /* For algorithm correctness, jump table for a single case must return + true. We bail out in is_beneficial if it's called just for + a single case. */ + if (start == end) + return true; + unsigned HOST_WIDE_INT max_ratio = optimize_insn_for_size_p () ? 3 : 8; unsigned HOST_WIDE_INT range = get_range (clusters[start]->get_low (), clusters[end]->get_high ()); /* Check overflow. */ @@ -1197,6 +1204,10 @@ bool jump_table_cluster::is_beneficial (const vec<cluster *> &, unsigned start, unsigned end) { + /* Single case bail out. */ + if (start == end) + return false; + return end - start + 1 >= case_values_threshold (); } @@ -1226,6 +1237,8 @@ bit_test_cluster::find_bit_tests (vec<cluster *> &clusters) && can_be_handled (clusters, j, i - 1)) min[i] = min_cluster_item (min[j].m_count + 1, j, INT_MAX); } + + gcc_checking_assert (min[i].m_count != INT_MAX); } /* No result. */ @@ -1277,6 +1290,12 @@ bool bit_test_cluster::can_be_handled (const vec<cluster *> &clusters, unsigned start, unsigned end) { + /* For algorithm correctness, bit test for a single case must return + true. We bail out in is_beneficial if it's called just for + a single case. */ + if (start == end) + return true; + unsigned HOST_WIDE_INT range = get_range (clusters[start]->get_low (), clusters[end]->get_high ()); auto_bitmap dest_bbs; @@ -1308,6 +1327,10 @@ bool bit_test_cluster::is_beneficial (const vec<cluster *> &clusters, unsigned start, unsigned end) { + /* Single case bail out. */ + if (start == end) + return false; + auto_bitmap dest_bbs; for (unsigned i = start; i <= end; i++) @@ -1599,7 +1622,7 @@ switch_decision_tree::analyze_switch_statement () /* Find jump table clusters. */ vec<cluster *> output = jump_table_cluster::find_jump_tables (clusters); - /* Find jump table clusters. */ + /* Find bit test clusters. */ vec<cluster *> output2; auto_vec<cluster *> tmp; output2.create (1); |