aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-switch-conversion.c
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2021-09-13 10:37:49 -0700
committerIan Lance Taylor <iant@golang.org>2021-09-13 10:37:49 -0700
commite252b51ccde010cbd2a146485d8045103cd99533 (patch)
treee060f101cdc32bf5e520de8e5275db9d4236b74c /gcc/tree-switch-conversion.c
parentf10c7c4596dda99d2ee872c995ae4aeda65adbdf (diff)
parent104c05c5284b7822d770ee51a7d91946c7e56d50 (diff)
downloadgcc-e252b51ccde010cbd2a146485d8045103cd99533.zip
gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.gz
gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.bz2
Merge from trunk revision 104c05c5284b7822d770ee51a7d91946c7e56d50.
Diffstat (limited to 'gcc/tree-switch-conversion.c')
-rw-r--r--gcc/tree-switch-conversion.c52
1 files changed, 30 insertions, 22 deletions
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index 7f65c4c..244cf4b 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -50,6 +50,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "target.h"
#include "tree-into-ssa.h"
#include "omp-general.h"
+#include "gimple-range.h"
/* ??? For lang_hooks.types.type_for_mode, but is there a word_mode
type in the GIMPLE type system that is language-independent? */
@@ -1090,7 +1091,7 @@ group_cluster::dump (FILE *f, bool details)
for (unsigned i = 0; i < m_cases.length (); i++)
{
simple_cluster *sc = static_cast<simple_cluster *> (m_cases[i]);
- comparison_count += sc->m_range_p ? 2 : 1;
+ comparison_count += sc->get_comparison_count ();
}
unsigned HOST_WIDE_INT range = get_range (get_low (), get_high ());
@@ -1185,11 +1186,24 @@ jump_table_cluster::find_jump_tables (vec<cluster *> &clusters)
min.quick_push (min_cluster_item (0, 0, 0));
+ unsigned HOST_WIDE_INT max_ratio
+ = (optimize_insn_for_size_p ()
+ ? param_jump_table_max_growth_ratio_for_size
+ : param_jump_table_max_growth_ratio_for_speed);
+
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));
+ /* Pre-calculate number of comparisons for the clusters. */
+ HOST_WIDE_INT comparison_count = 0;
+ for (unsigned k = 0; k <= i - 1; k++)
+ {
+ simple_cluster *sc = static_cast<simple_cluster *> (clusters[k]);
+ comparison_count += sc->get_comparison_count ();
+ }
+
for (unsigned j = 0; j < i; j++)
{
unsigned HOST_WIDE_INT s = min[j].m_non_jt_cases;
@@ -1200,10 +1214,15 @@ jump_table_cluster::find_jump_tables (vec<cluster *> &clusters)
if ((min[j].m_count + 1 < min[i].m_count
|| (min[j].m_count + 1 == min[i].m_count
&& s < min[i].m_non_jt_cases))
- && can_be_handled (clusters, j, i - 1))
+ && can_be_handled (clusters, j, i - 1, max_ratio,
+ comparison_count))
min[i] = min_cluster_item (min[j].m_count + 1, j, s);
+
+ simple_cluster *sc = static_cast<simple_cluster *> (clusters[j]);
+ comparison_count -= sc->get_comparison_count ();
}
+ gcc_checking_assert (comparison_count == 0);
gcc_checking_assert (min[i].m_count != INT_MAX);
}
@@ -1241,7 +1260,9 @@ jump_table_cluster::find_jump_tables (vec<cluster *> &clusters)
bool
jump_table_cluster::can_be_handled (const vec<cluster *> &clusters,
- unsigned start, unsigned end)
+ unsigned start, unsigned end,
+ unsigned HOST_WIDE_INT max_ratio,
+ unsigned HOST_WIDE_INT comparison_count)
{
/* If the switch is relatively small such that the cost of one
indirect jump on the target are higher than the cost of a
@@ -1260,10 +1281,6 @@ jump_table_cluster::can_be_handled (const vec<cluster *> &clusters,
if (start == end)
return true;
- unsigned HOST_WIDE_INT max_ratio
- = (optimize_insn_for_size_p ()
- ? param_jump_table_max_growth_ratio_for_size
- : param_jump_table_max_growth_ratio_for_speed);
unsigned HOST_WIDE_INT range = get_range (clusters[start]->get_low (),
clusters[end]->get_high ());
/* Check overflow. */
@@ -1277,18 +1294,6 @@ jump_table_cluster::can_be_handled (const vec<cluster *> &clusters,
if (lhs < range)
return false;
- /* First make quick guess as each cluster
- can add at maximum 2 to the comparison_count. */
- if (lhs > 2 * max_ratio * (end - start + 1))
- return false;
-
- unsigned HOST_WIDE_INT comparison_count = 0;
- for (unsigned i = start; i <= end; i++)
- {
- simple_cluster *sc = static_cast<simple_cluster *> (clusters[i]);
- comparison_count += sc->m_range_p ? 2 : 1;
- }
-
return lhs <= max_ratio * comparison_count;
}
@@ -1553,12 +1558,15 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
/* If every possible relative value of the index expression is a valid shift
amount, then we can merge the entry test in the bit test. */
- wide_int min, max;
bool entry_test_needed;
+ value_range r;
if (TREE_CODE (index_expr) == SSA_NAME
- && get_range_info (index_expr, &min, &max) == VR_RANGE
- && wi::leu_p (max - min, prec - 1))
+ && get_range_query (cfun)->range_of_expr (r, index_expr)
+ && r.kind () == VR_RANGE
+ && wi::leu_p (r.upper_bound () - r.lower_bound (), prec - 1))
{
+ wide_int min = r.lower_bound ();
+ wide_int max = r.upper_bound ();
tree index_type = TREE_TYPE (index_expr);
minval = fold_convert (index_type, minval);
wide_int iminval = wi::to_wide (minval);