switch lowering: limit number of cluster attemps
gcc/ChangeLog: PR tree-optimization/96979 * doc/invoke.texi: Document new param max-switch-clustering-attempts. * params.opt: Add new parameter. * tree-switch-conversion.c (jump_table_cluster::find_jump_tables): Limit number of attempts. (bit_test_cluster::find_bit_tests): Likewise. gcc/testsuite/ChangeLog: PR tree-optimization/96979 * g++.dg/tree-ssa/pr96979.C: New test.
This commit is contained in:
parent
1a84651d16
commit
c6df6039e9
@ -13452,6 +13452,10 @@ The smallest number of different values for which it is best to use a
|
||||
jump-table instead of a tree of conditional branches. If the value is
|
||||
0, use the default for the machine.
|
||||
|
||||
@item max-switch-clustering-attempts
|
||||
The maximum number of clustering attempts used
|
||||
in bit-test and jump-table switch expansion.
|
||||
|
||||
@item jump-table-max-growth-ratio-for-size
|
||||
The maximum code size growth ratio when expanding
|
||||
into a jump table (in percent). The parameter is used when
|
||||
|
@ -82,6 +82,10 @@ The maximum length of a constant string for a builtin string cmp call eligible f
|
||||
Common Joined UInteger Var(param_case_values_threshold) Param Optimization
|
||||
The smallest number of different values for which it is best to use a jump-table instead of a tree of conditional branches, if 0, use the default for the machine.
|
||||
|
||||
-param=max-switch-clustering-attempts=
|
||||
Common Joined UInteger Var(param_max_switch_clustering_attempts) Param Optimization Init(10000)
|
||||
The maximum number of clustering attempts used in bit-test and jump-table switch expansion.
|
||||
|
||||
-param=comdat-sharing-probability=
|
||||
Common Joined UInteger Var(param_comdat_sharing_probability) Init(20) Param Optimization
|
||||
Probability that COMDAT function will be shared with different compilation unit.
|
||||
|
50
gcc/testsuite/g++.dg/tree-ssa/pr96979.C
Normal file
50
gcc/testsuite/g++.dg/tree-ssa/pr96979.C
Normal file
@ -0,0 +1,50 @@
|
||||
/* PR tree-optimization/96979 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-std=c++17 -O2 -fdump-tree-switchlower1" } */
|
||||
|
||||
using u64 = unsigned long long;
|
||||
|
||||
constexpr inline u64
|
||||
foo (const char *str) noexcept
|
||||
{
|
||||
u64 value = 0xcbf29ce484222325ULL;
|
||||
for (u64 i = 0; str[i]; i++)
|
||||
value = (value ^ u64(str[i])) * 0x100000001b3ULL;
|
||||
return value;
|
||||
}
|
||||
|
||||
struct V
|
||||
{
|
||||
enum W
|
||||
{
|
||||
#define A(n) n,
|
||||
#define B(n) A(n##0) A(n##1) A(n##2) A(n##3) A(n##4) A(n##5) A(n##6) A(n##7) A(n##8) A(n##9)
|
||||
#define C(n) B(n##0) B(n##1) B(n##2) B(n##3) B(n##4) B(n##5) B(n##6) B(n##7) B(n##8) B(n##9)
|
||||
#define D(n) C(n##0) C(n##1) C(n##2) C(n##3) C(n##4) C(n##5) C(n##6) C(n##7) C(n##8) C(n##9)
|
||||
#define E D(foo1) D(foo2) D(foo3)
|
||||
E
|
||||
last
|
||||
};
|
||||
|
||||
constexpr static W
|
||||
bar (const u64 h) noexcept
|
||||
{
|
||||
switch (h)
|
||||
{
|
||||
#undef A
|
||||
#define F(n) #n
|
||||
#define A(n) case foo (F(n)): return n;
|
||||
E
|
||||
}
|
||||
return last;
|
||||
}
|
||||
};
|
||||
|
||||
int
|
||||
baz (const char *s)
|
||||
{
|
||||
const u64 h = foo (s);
|
||||
return V::bar (h);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times ";; Bail out: --param=max-switch-clustering-attempts reached" 2 "switchlower1" } } */
|
@ -1183,6 +1183,7 @@ jump_table_cluster::find_jump_tables (vec<cluster *> &clusters)
|
||||
|
||||
min.quick_push (min_cluster_item (0, 0, 0));
|
||||
|
||||
HOST_WIDE_INT attempts = 0;
|
||||
for (unsigned i = 1; i <= l; i++)
|
||||
{
|
||||
/* Set minimal # of clusters with i-th item to infinite. */
|
||||
@ -1194,6 +1195,14 @@ jump_table_cluster::find_jump_tables (vec<cluster *> &clusters)
|
||||
if (i - j < case_values_threshold ())
|
||||
s += i - j;
|
||||
|
||||
if (attempts++ == param_max_switch_clustering_attempts)
|
||||
{
|
||||
if (dump_file)
|
||||
fprintf (dump_file, ";; Bail out: "
|
||||
"--param=max-switch-clustering-attempts reached\n");
|
||||
return clusters.copy ();
|
||||
}
|
||||
|
||||
/* Prefer clusters with smaller number of numbers covered. */
|
||||
if ((min[j].m_count + 1 < min[i].m_count
|
||||
|| (min[j].m_count + 1 == min[i].m_count
|
||||
@ -1308,6 +1317,7 @@ bit_test_cluster::find_bit_tests (vec<cluster *> &clusters)
|
||||
|
||||
min.quick_push (min_cluster_item (0, 0, 0));
|
||||
|
||||
HOST_WIDE_INT attempts = 0;
|
||||
for (unsigned i = 1; i <= l; i++)
|
||||
{
|
||||
/* Set minimal # of clusters with i-th item to infinite. */
|
||||
@ -1315,6 +1325,13 @@ bit_test_cluster::find_bit_tests (vec<cluster *> &clusters)
|
||||
|
||||
for (unsigned j = 0; j < i; j++)
|
||||
{
|
||||
if (attempts++ == param_max_switch_clustering_attempts)
|
||||
{
|
||||
if (dump_file)
|
||||
fprintf (dump_file, ";; Bail out: "
|
||||
"--param=max-switch-clustering-attempts reached\n");
|
||||
return clusters.copy ();
|
||||
}
|
||||
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user