aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-switch-conversion.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-switch-conversion.cc')
-rw-r--r--gcc/tree-switch-conversion.cc245
1 files changed, 73 insertions, 172 deletions
diff --git a/gcc/tree-switch-conversion.cc b/gcc/tree-switch-conversion.cc
index 39a8a89..dea217a 100644
--- a/gcc/tree-switch-conversion.cc
+++ b/gcc/tree-switch-conversion.cc
@@ -1773,122 +1773,108 @@ jump_table_cluster::is_beneficial (const vec<cluster *> &,
return end - start + 1 >= case_values_threshold ();
}
-/* Find bit tests of given CLUSTERS, where all members of the vector are of
- type simple_cluster. Use a fast algorithm that might not find the optimal
- solution (minimal number of clusters on the output). New clusters are
- returned.
-
- You should call find_bit_tests () instead of calling this function
- directly. */
+/* Find bit tests of given CLUSTERS, where all members of the vector
+ are of type simple_cluster. MAX_C is the approx max number of cases per
+ label. New clusters are returned. */
vec<cluster *>
-bit_test_cluster::find_bit_tests_fast (vec<cluster *> &clusters)
+bit_test_cluster::find_bit_tests (vec<cluster *> &clusters, int max_c)
{
- unsigned l = clusters.length ();
- vec<cluster *> output;
+ if (!is_enabled () || max_c == 1)
+ return clusters.copy ();
- output.create (l);
+ /* Dynamic programming algorithm.
- /* Look at sliding BITS_PER_WORD sized windows in the switch value space
- and determine if they are suitable for a bit test cluster. Worst case
- this can examine every value BITS_PER_WORD-1 times. */
- unsigned k;
- for (unsigned i = 0; i < l; i += k)
- {
- hash_set<basic_block> targets;
- cluster *start_cluster = clusters[i];
+ In: List of simple clusters
+ Out: List of simple clusters and bit test clusters such that each bit test
+ cluster can_be_handled() and is_beneficial()
- /* Find the biggest k such that clusters i to i+k-1 can be turned into a
- one big bit test cluster. */
- k = 0;
- while (i + k < l)
- {
- cluster *end_cluster = clusters[i + k];
+ Tries to merge consecutive clusters into bigger (bit test) ones. Tries to
+ end up with as few clusters as possible. */
- /* Does value range fit into the BITS_PER_WORD window? */
- HOST_WIDE_INT w = cluster::get_range (start_cluster->get_low (),
- end_cluster->get_high ());
- if (w == 0 || w > BITS_PER_WORD)
- break;
+ unsigned l = clusters.length ();
+ auto_vec<min_cluster_item> min;
+ min.reserve (l + 1);
- /* Check for max # of targets. */
- if (targets.elements () == m_max_case_bit_tests
- && !targets.contains (end_cluster->m_case_bb))
- break;
+ gcc_checking_assert (l > 0);
+ gcc_checking_assert (l <= INT_MAX);
- targets.add (end_cluster->m_case_bb);
- k++;
- }
+ int bits_in_word = GET_MODE_BITSIZE (word_mode);
- if (is_beneficial (k, targets.elements ()))
- {
- output.safe_push (new bit_test_cluster (clusters, i, i + k - 1,
- i == 0 && k == l));
- }
- else
- {
- output.safe_push (clusters[i]);
- /* ??? Might be able to skip more. */
- k = 1;
- }
- }
+ /* First phase: Compute the minimum number of clusters for each prefix of the
+ input list incrementally
- return output;
-}
-
-/* Find bit tests of given CLUSTERS, where all members of the vector
- are of type simple_cluster. Use a slow (quadratic) algorithm that always
- finds the optimal solution (minimal number of clusters on the output). New
- clusters are returned.
+ min[i] = (count, j, _) means that the prefix ending with the (i-1)-th
+ element can be made to contain as few as count clusters and that in such
+ clustering the last cluster is made up of input clusters [j, i-1]
+ (inclusive). */
+ min.quick_push (min_cluster_item (0, 0, INT_MAX));
+ min.quick_push (min_cluster_item (1, 0, INT_MAX));
+ for (int i = 2; i <= (int) l; i++)
+ {
+ auto_vec<unsigned, m_max_case_bit_tests> unique_labels;
- You should call find_bit_tests () instead of calling this function
- directly. */
+ /* Since each cluster contains at least one case number and one bit test
+ cluster can cover at most bits_in_word case numbers, we don't need to
+ look farther than bits_in_word clusters back. */
+ for (int j = i - 1; j >= 0 && j >= i - bits_in_word; j--)
+ {
+ /* Consider creating a bit test cluster from input clusters [j, i-1]
+ (inclusive) */
-vec<cluster *>
-bit_test_cluster::find_bit_tests_slow (vec<cluster *> &clusters)
-{
- unsigned l = clusters.length ();
- auto_vec<min_cluster_item> min;
- min.reserve (l + 1);
+ simple_cluster *sc = static_cast<simple_cluster *> (clusters[j]);
+ unsigned label = sc->m_case_bb->index;
+ if (!unique_labels.contains (label))
+ {
+ if (unique_labels.length () >= m_max_case_bit_tests)
+ /* is_beneficial() will be false for this and the following
+ iterations. */
+ break;
+ unique_labels.quick_push (label);
+ }
- min.quick_push (min_cluster_item (0, 0, 0));
+ unsigned new_count = min[j].m_count + 1;
- for (unsigned i = 1; i <= l; i++)
- {
- /* Set minimal # of clusters with i-th item to infinite. */
- min.quick_push (min_cluster_item (INT_MAX, INT_MAX, INT_MAX));
+ if (j == i - 1)
+ {
+ min.quick_push (min_cluster_item (new_count, j, INT_MAX));
+ continue;
+ }
- for (unsigned j = 0; j < i; j++)
- {
- if (min[j].m_count + 1 < min[i].m_count
- && can_be_handled (clusters, j, i - 1))
- min[i] = min_cluster_item (min[j].m_count + 1, j, INT_MAX);
+ unsigned HOST_WIDE_INT range
+ = get_range (clusters[j]->get_low (), clusters[i-1]->get_high ());
+ if (new_count < min[i].m_count
+ && can_be_handled (range, unique_labels.length ())
+ && is_beneficial (i - j, unique_labels.length ()))
+ min[i] = min_cluster_item (new_count, j, INT_MAX);
}
-
- gcc_checking_assert (min[i].m_count != INT_MAX);
}
- /* No result. */
if (min[l].m_count == l)
+ /* No bit test clustering opportunities. */
return clusters.copy ();
vec<cluster *> output;
output.create (4);
- /* Find and build the clusters. */
+ /* Second phase: Find and build the bit test clusters by traversing min
+ array backwards. */
for (unsigned end = l;;)
{
- int start = min[end].m_start;
+ unsigned start = min[end].m_start;
+ gcc_checking_assert (start < end);
- if (is_beneficial (clusters, start, end - 1))
+ /* This cluster will be made out of input clusters [start, end - 1]. */
+
+ if (start == end - 1)
+ /* Let the cluster be a simple cluster. */
+ output.safe_push (clusters[start]);
+ else
{
- bool entire = start == 0 && end == clusters.length ();
+ bool entire = start == 0 && end == l;
output.safe_push (new bit_test_cluster (clusters, start, end - 1,
entire));
}
- else
- for (int i = end - 1; i >= start; i--)
- output.safe_push (clusters[i]);
end = start;
@@ -1900,25 +1886,6 @@ bit_test_cluster::find_bit_tests_slow (vec<cluster *> &clusters)
return output;
}
-/* Find bit tests of given CLUSTERS, where all members of the vector
- are of type simple_cluster. MAX_C is the approx max number of cases per
- label. New clusters are returned. */
-
-vec<cluster *>
-bit_test_cluster::find_bit_tests (vec<cluster *> &clusters, int max_c)
-{
- if (!is_enabled () || max_c == 1)
- return clusters.copy ();
-
- unsigned l = clusters.length ();
-
- /* Note: l + 1 is the number of cases of the switch. */
- if (l + 1 > (unsigned) param_switch_lower_slow_alg_max_cases)
- return find_bit_tests_fast (clusters);
- else
- return find_bit_tests_slow (clusters);
-}
-
/* Return true when RANGE of case values with UNIQ labels
can build a bit test. */
@@ -1930,84 +1897,25 @@ bit_test_cluster::can_be_handled (unsigned HOST_WIDE_INT range,
if (range == 0)
return false;
- if (range >= GET_MODE_BITSIZE (word_mode))
+ if (range > GET_MODE_BITSIZE (word_mode))
return false;
return uniq <= m_max_case_bit_tests;
}
-/* Return true when cluster starting at START and ending at END (inclusive)
- can build a bit test. */
-
-bool
-bit_test_cluster::can_be_handled (const vec<cluster *> &clusters,
- unsigned start, unsigned end)
-{
- auto_vec<int, m_max_case_bit_tests> dest_bbs;
- /* 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 ());
-
- /* Make a guess first. */
- if (!can_be_handled (range, m_max_case_bit_tests))
- return false;
-
- for (unsigned i = start; i <= end; i++)
- {
- simple_cluster *sc = static_cast<simple_cluster *> (clusters[i]);
- /* m_max_case_bit_tests is very small integer, thus the operation
- is constant. */
- if (!dest_bbs.contains (sc->m_case_bb->index))
- {
- if (dest_bbs.length () >= m_max_case_bit_tests)
- return false;
- dest_bbs.quick_push (sc->m_case_bb->index);
- }
- }
-
- return true;
-}
-
/* Return true when COUNT of cases of UNIQ labels is beneficial for bit test
transformation. */
bool
bit_test_cluster::is_beneficial (unsigned count, unsigned uniq)
{
+ /* NOTE: When modifying this, keep in mind the value of
+ m_max_case_bit_tests. */
return (((uniq == 1 && count >= 3)
|| (uniq == 2 && count >= 5)
|| (uniq == 3 && count >= 6)));
}
-/* Return true if cluster starting at START and ending at END (inclusive)
- is profitable transformation. */
-
-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++)
- {
- simple_cluster *sc = static_cast<simple_cluster *> (clusters[i]);
- bitmap_set_bit (dest_bbs, sc->m_case_bb->index);
- }
-
- unsigned uniq = bitmap_count_bits (dest_bbs);
- unsigned count = end - start + 1;
- return is_beneficial (count, uniq);
-}
-
/* Comparison function for qsort to order bit tests by decreasing
probability of execution. */
@@ -2349,13 +2257,6 @@ switch_decision_tree::analyze_switch_statement ()
reset_out_edges_aux (m_switch);
- if (l > (unsigned) param_switch_lower_slow_alg_max_cases)
- warning_at (gimple_location (m_switch), OPT_Wdisabled_optimization,
- "Using faster switch lowering algorithms. "
- "Number of switch cases (%d) exceeds "
- "%<--param=switch-lower-slow-alg-max-cases=%d%> limit.",
- l, param_switch_lower_slow_alg_max_cases);
-
/* Find bit-test clusters. */
vec<cluster *> output = bit_test_cluster::find_bit_tests (clusters, max_c);