From 1d9cd701ec31686dbd037e0fe264c8738d993e41 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 29 Aug 2019 11:20:54 +0200 Subject: [PATCH] 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 --- gcc/ChangeLog | 16 +++++++++++++ gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/g++.dg/opt/pr91351.C | 38 ++++++++++++++++++++++++++++++ gcc/tree-cfg.c | 2 +- gcc/tree-cfgcleanup.c | 2 ++ gcc/tree-switch-conversion.c | 22 +++++++++-------- 6 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/g++.dg/opt/pr91351.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 49ab435387b..6342c4ac2f3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2019-08-29 Jakub Jelinek + + 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 PR tree-optimization/91568 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a051dda738e..652759a5ac1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-08-29 Jakub Jelinek + + PR tree-optimization/91351 + * g++.dg/opt/pr91351.C: New test. + 2019-08-29 Paolo Carlini * g++.dg/spellcheck-typenames.C: Adjust expected locations. diff --git a/gcc/testsuite/g++.dg/opt/pr91351.C b/gcc/testsuite/g++.dg/opt/pr91351.C new file mode 100644 index 00000000000..f793a2f1b11 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr91351.C @@ -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); +} diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 2648663204b..b75fdb2e63f 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -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); diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c index 183b491ab1d..4bac38ab00c 100644 --- a/gcc/tree-cfgcleanup.c +++ b/gcc/tree-cfgcleanup.c @@ -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); } diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c index 776db77f53a..e8692a7fffe 100644 --- a/gcc/tree-switch-conversion.c +++ b/gcc/tree-switch-conversion.c @@ -605,7 +605,9 @@ switch_conversion::build_one_array (int num, tree arr_index_type, vec *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 &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 &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. */