aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilip Kastl <fkastl@suse.cz>2025-05-01 15:30:52 +0200
committerFilip Kastl <fkastl@suse.cz>2025-05-02 11:51:22 +0200
commit5274db0c9b8c0e2d2879b237eb2ab576543b6c37 (patch)
tree76863f1676c31ef9731378c9a017ce816585a13d
parent02fa088f5b61fb5ddfff9e2dc0c0404450e7c6a4 (diff)
downloadgcc-5274db0c9b8c0e2d2879b237eb2ab576543b6c37.zip
gcc-5274db0c9b8c0e2d2879b237eb2ab576543b6c37.tar.gz
gcc-5274db0c9b8c0e2d2879b237eb2ab576543b6c37.tar.bz2
gimple: Merge slow and fast bit-test switch lowering [PR117091]
PR117091 showed that bit-test switch lowering can take a lot of time. The algorithm was O(n^2). We therefore came up with a faster algorithm (O(n * BITS_IN_WORD)) and made GCC choose between the slow and the fast algorithm based on how big the switch is. Here I combine the algorithms so that we get the results of the slower algorithm in the faster asymptotic time. PR middle-end/117091 gcc/ChangeLog: * tree-switch-conversion.cc (bit_test_cluster::find_bit_tests_fast): Remove function. (bit_test_cluster::find_bit_tests_slow): Remove function. (bit_test_cluster::find_bit_tests): We don't need to decide between slow and fast so just put the modified (no longer) slow algorithm here. Signed-off-by: Filip Kastl <fkastl@suse.cz>
-rw-r--r--gcc/tree-switch-conversion.cc107
1 files changed, 17 insertions, 90 deletions
diff --git a/gcc/tree-switch-conversion.cc b/gcc/tree-switch-conversion.cc
index 39a8a89..a70274b 100644
--- a/gcc/tree-switch-conversion.cc
+++ b/gcc/tree-switch-conversion.cc
@@ -1773,92 +1773,38 @@ 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. */
-
-vec<cluster *>
-bit_test_cluster::find_bit_tests_fast (vec<cluster *> &clusters)
-{
- unsigned l = clusters.length ();
- vec<cluster *> output;
-
- output.create (l);
-
- /* 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];
-
- /* 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];
-
- /* 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;
-
- /* Check for max # of targets. */
- if (targets.elements () == m_max_case_bit_tests
- && !targets.contains (end_cluster->m_case_bb))
- break;
-
- targets.add (end_cluster->m_case_bb);
- k++;
- }
-
- 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;
- }
- }
-
- 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.
-
- You should call find_bit_tests () instead of calling this function
- directly. */
+ 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_slow (vec<cluster *> &clusters)
+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 ();
auto_vec<min_cluster_item> min;
min.reserve (l + 1);
min.quick_push (min_cluster_item (0, 0, 0));
+ unsigned bits_in_word = GET_MODE_BITSIZE (word_mode);
+
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));
- for (unsigned j = 0; j < i; j++)
+ /* 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. */
+ unsigned j;
+ if (i - 1 >= bits_in_word)
+ j = i - 1 - bits_in_word;
+ else
+ j = 0;
+ for (; j < i; j++)
{
if (min[j].m_count + 1 < min[i].m_count
&& can_be_handled (clusters, j, i - 1))
@@ -1900,25 +1846,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. */