summaryrefslogtreecommitdiff
path: root/gcc/stmt.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2010-11-19 23:48:57 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2010-11-19 23:48:57 +0000
commitdf2813c5d1134b21d1833567129a6aaafc52a3fd (patch)
treee65b38b3e2f234c14ced25bd4b7e019d0bf01d3f /gcc/stmt.c
parent021916134abceb9c085345986b4afd61eb066ef3 (diff)
downloadgcc-df2813c5d1134b21d1833567129a6aaafc52a3fd.tar.gz
PR tree-optimization/45830
* stmt.c (expand_switch_using_bit_tests_p): New function. (expand_case): Use it. * tree.h (expand_switch_using_bit_tests_p): New prototype. * tree-switch-conversion.c (struct switch_conv_info): Add bit_test_uniq, bit_test_count and bit_test_bb fields. (check_range): Fix a comment. (check_process_case): Compute bit_test_uniq and bit_test_count. (create_temp_arrays): Use XCNEWVEC, merge 3 arrays into one allocation. (free_temp_arrays): Use XDELETEVEC, adjust for the 3 arrays merging. (constructor_contains_same_values_p): Use FOR_EACH_VEC_ELT. (array_value_type): New function. (build_one_array): Use it, if it returned different type, fold_convert all constructor fields and convert back to the wider type in the generated code. (process_switch): Initialize bit_test_uniq, bit_test_count and bit_test_bb fields. Don't optimize if expand_switch_using_bit_tests_p returned true. * gcc.target/i386/pr45830.c: New test. * gcc.c-torture/execute/pr45830.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166966 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/stmt.c')
-rw-r--r--gcc/stmt.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/gcc/stmt.c b/gcc/stmt.c
index e24ed4ebb31..e045330ef31 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -2250,6 +2250,25 @@ emit_case_bit_tests (tree index_type, tree index_expr, tree minval,
#define HAVE_tablejump 0
#endif
+/* Return true if a switch should be expanded as a bit test.
+ INDEX_EXPR is the index expression, RANGE is the difference between
+ highest and lowest case, UNIQ is number of unique case node targets
+ not counting the default case and COUNT is the number of comparisons
+ needed, not counting the default case. */
+bool
+expand_switch_using_bit_tests_p (tree index_expr, tree range,
+ unsigned int uniq, unsigned int count)
+{
+ return (CASE_USE_BIT_TESTS
+ && ! TREE_CONSTANT (index_expr)
+ && compare_tree_int (range, GET_MODE_BITSIZE (word_mode)) < 0
+ && compare_tree_int (range, 0) > 0
+ && lshift_cheap_p ()
+ && ((uniq == 1 && count >= 3)
+ || (uniq == 2 && count >= 5)
+ || (uniq == 3 && count >= 6)));
+}
+
/* Terminate a case (Pascal/Ada) or switch (C) statement
in which ORIG_INDEX is the expression to be tested.
If ORIG_TYPE is not NULL, it is the original ORIG_INDEX
@@ -2384,14 +2403,7 @@ expand_case (gimple stmt)
/* Try implementing this switch statement by a short sequence of
bit-wise comparisons. However, we let the binary-tree case
below handle constant index expressions. */
- if (CASE_USE_BIT_TESTS
- && ! TREE_CONSTANT (index_expr)
- && compare_tree_int (range, GET_MODE_BITSIZE (word_mode)) < 0
- && compare_tree_int (range, 0) > 0
- && lshift_cheap_p ()
- && ((uniq == 1 && count >= 3)
- || (uniq == 2 && count >= 5)
- || (uniq == 3 && count >= 6)))
+ if (expand_switch_using_bit_tests_p (index_expr, range, uniq, count))
{
/* Optimize the case where all the case values fit in a
word without having to subtract MINVAL. In this case,