re PR tree-optimization/91351 (-fstrict-enums generates incorrect code)

PR tree-optimization/91351
	* tree-cfg.c (generate_range_test): Use range_check_type instead of
	unsigned_type_for.
	* tree-cfgcleanup.c (convert_single_case_switch): Punt if
	range_check_type returns NULL.
	* tree-switch-conversion.c (switch_conversion::build_one_array):
	Use range_check_type instead of unsigned_type_for, don't perform
	linear opt if it returns NULL.
	(bit_test_cluster::find_bit_tests): Formatting fix.
	(bit_test_cluster::emit): Use range_check_type instead of
	unsigned_type_for.
	(switch_decision_tree::try_switch_expansion): Punt if range_check_type
	returns NULL.

	* g++.dg/opt/pr91351.C: New test.

From-SVN: r275026
This commit is contained in:
Jakub Jelinek 2019-08-29 11:20:54 +02:00 committed by Jakub Jelinek
parent c3bad34748
commit 1d9cd701ec
6 changed files with 74 additions and 11 deletions

View File

@ -1,3 +1,19 @@
2019-08-29 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/91351
* tree-cfg.c (generate_range_test): Use range_check_type instead of
unsigned_type_for.
* tree-cfgcleanup.c (convert_single_case_switch): Punt if
range_check_type returns NULL.
* tree-switch-conversion.c (switch_conversion::build_one_array):
Use range_check_type instead of unsigned_type_for, don't perform
linear opt if it returns NULL.
(bit_test_cluster::find_bit_tests): Formatting fix.
(bit_test_cluster::emit): Use range_check_type instead of
unsigned_type_for.
(switch_decision_tree::try_switch_expansion): Punt if range_check_type
returns NULL.
2019-08-29 Richard Biener <rguenther@suse.de>
PR tree-optimization/91568

View File

@ -1,3 +1,8 @@
2019-08-29 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/91351
* g++.dg/opt/pr91351.C: New test.
2019-08-29 Paolo Carlini <paolo.carlini@oracle.com>
* g++.dg/spellcheck-typenames.C: Adjust expected locations.

View File

@ -0,0 +1,38 @@
// PR tree-optimization/91351
// { dg-do run }
// { dg-options "-O2 -fstrict-enums" }
enum E { e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12,
e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25 };
__attribute__((noipa)) void
foo ()
{
__builtin_abort ();
}
__attribute__((noipa)) void
bar ()
{
}
__attribute__((noipa)) void
baz (E e)
{
switch (e)
{
case e11:
case e12:
case e13: foo (); break;
case e24: break;
case e14:
case e15: break;
default: bar (); break;
}
}
int
main ()
{
baz (e3);
}

View File

@ -9221,7 +9221,7 @@ generate_range_test (basic_block bb, tree index, tree low, tree high,
tree *lhs, tree *rhs)
{
tree type = TREE_TYPE (index);
tree utype = unsigned_type_for (type);
tree utype = range_check_type (type);
low = fold_convert (utype, low);
high = fold_convert (utype, high);

View File

@ -101,6 +101,8 @@ convert_single_case_switch (gswitch *swtch, gimple_stmt_iterator &gsi)
if (high)
{
tree lhs, rhs;
if (range_check_type (TREE_TYPE (index)) == NULL_TREE)
return false;
generate_range_test (bb, index, low, high, &lhs, &rhs);
cond = gimple_build_cond (LE_EXPR, lhs, rhs, NULL_TREE, NULL_TREE);
}

View File

@ -605,7 +605,9 @@ switch_conversion::build_one_array (int num, tree arr_index_type,
vec<constructor_elt, va_gc> *constructor = m_constructors[num];
wide_int coeff_a, coeff_b;
bool linear_p = contains_linear_function_p (constructor, &coeff_a, &coeff_b);
if (linear_p)
tree type;
if (linear_p
&& (type = range_check_type (TREE_TYPE ((*constructor)[0].value))))
{
if (dump_file && coeff_a.to_uhwi () > 0)
fprintf (dump_file, "Linear transformation with A = %" PRId64
@ -613,13 +615,12 @@ switch_conversion::build_one_array (int num, tree arr_index_type,
coeff_b.to_shwi ());
/* We must use type of constructor values. */
tree t = unsigned_type_for (TREE_TYPE ((*constructor)[0].value));
gimple_seq seq = NULL;
tree tmp = gimple_convert (&seq, t, m_index_expr);
tree tmp2 = gimple_build (&seq, MULT_EXPR, t,
wide_int_to_tree (t, coeff_a), tmp);
tree tmp3 = gimple_build (&seq, PLUS_EXPR, t, tmp2,
wide_int_to_tree (t, coeff_b));
tree tmp = gimple_convert (&seq, type, m_index_expr);
tree tmp2 = gimple_build (&seq, MULT_EXPR, type,
wide_int_to_tree (type, coeff_a), tmp);
tree tmp3 = gimple_build (&seq, PLUS_EXPR, type, tmp2,
wide_int_to_tree (type, coeff_b));
tree tmp4 = gimple_convert (&seq, TREE_TYPE (name), tmp3);
gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
load = gimple_build_assign (name, tmp4);
@ -1351,7 +1352,7 @@ bit_test_cluster::find_bit_tests (vec<cluster *> &clusters)
entire));
}
else
for (int i = end - 1; i >= start; i--)
for (int i = end - 1; i >= start; i--)
output.safe_push (clusters[i]);
end = start;
@ -1484,7 +1485,7 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
unsigned int i, j, k;
unsigned int count;
tree unsigned_index_type = unsigned_type_for (index_type);
tree unsigned_index_type = range_check_type (index_type);
gimple_stmt_iterator gsi;
gassign *shift_stmt;
@ -1794,7 +1795,8 @@ switch_decision_tree::try_switch_expansion (vec<cluster *> &clusters)
tree index_type = TREE_TYPE (index_expr);
basic_block bb = gimple_bb (m_switch);
if (gimple_switch_num_labels (m_switch) == 1)
if (gimple_switch_num_labels (m_switch) == 1
|| range_check_type (index_type) == NULL_TREE)
return false;
/* Find the default case target label. */