Commit 0cd2402d by Steven Bosscher

targhooks.c (default_case_values_threshold): Fix code style nit.

gcc/
	* targhooks.c (default_case_values_threshold): Fix code style nit.

	* stmt.c (add_case_node, expand_case): Move logic to remove/reduce
	case range and type folding from here...
	* gimplify.c (gimplify_switch_expr): ... to here.  Expect NULL_TREE
	type, as documented in tree.def

fortran/
	* trans-decl.c (gfc_trans_entry_master_switch): Build SWITCH_EXPR
	with NULL_TREE type instead of void_type_node.
	* trans-io.c (io_result): Likewise.
	* trans-stmt.c (gfc_trans_integer_select,
	gfc_trans_character_select): Likewise.

go/
	* go-gcc.cc (Gcc_backend::switch_statement): Build SWITCH_EXPR
	with NULL_TREE type instead of void_type_node.

From-SVN: r186579
parent 474ffc72
2012-04-18 Steven Bosscher <steven@gcc.gnu.org>
* targhooks.c (default_case_values_threshold): Fix code style nit.
* stmt.c (add_case_node, expand_case): Move logic to remove/reduce
case range and type folding from here...
* gimplify.c (gimplify_switch_expr): ... to here. Expect NULL_TREE
type, as documented in tree.def
2012-04-18 Jan Hubicka <jh@suse.cz> 2012-04-18 Jan Hubicka <jh@suse.cz>
* cgraph.h (verify_symtab, verify_symtab_node, verify_symtab_base): * cgraph.h (verify_symtab, verify_symtab_node, verify_symtab_base):
......
2012-04-18 Steven Bosscher <steven@gcc.gnu.org>
* trans-decl.c (gfc_trans_entry_master_switch): Build SWITCH_EXPR
with NULL_TREE type instead of void_type_node.
* trans-io.c (io_result): Likewise.
* trans-stmt.c (gfc_trans_integer_select,
gfc_trans_character_select): Likewise.
2012-04-16 Tobias Burnus <burnus@net-b.de> 2012-04-16 Tobias Burnus <burnus@net-b.de>
PR fortran/52864 PR fortran/52864
......
...@@ -4749,7 +4749,8 @@ gfc_trans_entry_master_switch (gfc_entry_list * el) ...@@ -4749,7 +4749,8 @@ gfc_trans_entry_master_switch (gfc_entry_list * el)
tmp = gfc_finish_block (&block); tmp = gfc_finish_block (&block);
/* The first argument selects the entry point. */ /* The first argument selects the entry point. */
val = DECL_ARGUMENTS (current_function_decl); val = DECL_ARGUMENTS (current_function_decl);
tmp = build3_v (SWITCH_EXPR, val, tmp, NULL_TREE); tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
val, tmp, NULL_TREE);
return tmp; return tmp;
} }
......
...@@ -882,7 +882,8 @@ io_result (stmtblock_t * block, tree var, gfc_st_label * err_label, ...@@ -882,7 +882,8 @@ io_result (stmtblock_t * block, tree var, gfc_st_label * err_label,
rc, build_int_cst (TREE_TYPE (rc), rc, build_int_cst (TREE_TYPE (rc),
IOPARM_common_libreturn_mask)); IOPARM_common_libreturn_mask));
tmp = build3_v (SWITCH_EXPR, rc, tmp, NULL_TREE); tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
rc, tmp, NULL_TREE);
gfc_add_expr_to_block (block, tmp); gfc_add_expr_to_block (block, tmp);
} }
......
...@@ -1918,7 +1918,8 @@ gfc_trans_integer_select (gfc_code * code) ...@@ -1918,7 +1918,8 @@ gfc_trans_integer_select (gfc_code * code)
} }
tmp = gfc_finish_block (&body); tmp = gfc_finish_block (&body);
tmp = build3_v (SWITCH_EXPR, se.expr, tmp, NULL_TREE); tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
se.expr, tmp, NULL_TREE);
gfc_add_expr_to_block (&block, tmp); gfc_add_expr_to_block (&block, tmp);
tmp = build1_v (LABEL_EXPR, end_label); tmp = build1_v (LABEL_EXPR, end_label);
...@@ -2203,7 +2204,8 @@ gfc_trans_character_select (gfc_code *code) ...@@ -2203,7 +2204,8 @@ gfc_trans_character_select (gfc_code *code)
gfc_add_block_to_block (&block, &expr1se.post); gfc_add_block_to_block (&block, &expr1se.post);
tmp = gfc_finish_block (&body); tmp = gfc_finish_block (&body);
tmp = build3_v (SWITCH_EXPR, case_num, tmp, NULL_TREE); tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
case_num, tmp, NULL_TREE);
gfc_add_expr_to_block (&block, tmp); gfc_add_expr_to_block (&block, tmp);
tmp = build1_v (LABEL_EXPR, end_label); tmp = build1_v (LABEL_EXPR, end_label);
...@@ -2349,7 +2351,8 @@ gfc_trans_character_select (gfc_code *code) ...@@ -2349,7 +2351,8 @@ gfc_trans_character_select (gfc_code *code)
gfc_add_block_to_block (&block, &expr1se.post); gfc_add_block_to_block (&block, &expr1se.post);
tmp = gfc_finish_block (&body); tmp = gfc_finish_block (&body);
tmp = build3_v (SWITCH_EXPR, case_num, tmp, NULL_TREE); tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
case_num, tmp, NULL_TREE);
gfc_add_expr_to_block (&block, tmp); gfc_add_expr_to_block (&block, tmp);
tmp = build1_v (LABEL_EXPR, end_label); tmp = build1_v (LABEL_EXPR, end_label);
......
...@@ -1575,6 +1575,10 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p) ...@@ -1575,6 +1575,10 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
tree switch_expr = *expr_p; tree switch_expr = *expr_p;
gimple_seq switch_body_seq = NULL; gimple_seq switch_body_seq = NULL;
enum gimplify_status ret; enum gimplify_status ret;
tree index_type = TREE_TYPE (switch_expr);
if (index_type == NULL_TREE)
index_type = TREE_TYPE (SWITCH_COND (switch_expr));
gcc_assert (INTEGRAL_TYPE_P (index_type));
ret = gimplify_expr (&SWITCH_COND (switch_expr), pre_p, NULL, is_gimple_val, ret = gimplify_expr (&SWITCH_COND (switch_expr), pre_p, NULL, is_gimple_val,
fb_rvalue); fb_rvalue);
...@@ -1585,6 +1589,7 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p) ...@@ -1585,6 +1589,7 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
{ {
VEC (tree,heap) *labels; VEC (tree,heap) *labels;
VEC (tree,heap) *saved_labels; VEC (tree,heap) *saved_labels;
tree min_value, max_value;
tree default_case = NULL_TREE; tree default_case = NULL_TREE;
size_t i, len; size_t i, len;
gimple gimple_switch; gimple gimple_switch;
...@@ -1593,7 +1598,7 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p) ...@@ -1593,7 +1598,7 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
be bothered to null out the body too. */ be bothered to null out the body too. */
gcc_assert (!SWITCH_LABELS (switch_expr)); gcc_assert (!SWITCH_LABELS (switch_expr));
/* save old labels, get new ones from body, then restore the old /* Save old labels, get new ones from body, then restore the old
labels. Save all the things from the switch body to append after. */ labels. Save all the things from the switch body to append after. */
saved_labels = gimplify_ctxp->case_labels; saved_labels = gimplify_ctxp->case_labels;
gimplify_ctxp->case_labels = VEC_alloc (tree, heap, 8); gimplify_ctxp->case_labels = VEC_alloc (tree, heap, 8);
...@@ -1603,18 +1608,82 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p) ...@@ -1603,18 +1608,82 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
gimplify_ctxp->case_labels = saved_labels; gimplify_ctxp->case_labels = saved_labels;
i = 0; i = 0;
min_value = TYPE_MIN_VALUE (index_type);
max_value = TYPE_MAX_VALUE (index_type);
while (i < VEC_length (tree, labels)) while (i < VEC_length (tree, labels))
{ {
tree elt = VEC_index (tree, labels, i); tree elt = VEC_index (tree, labels, i);
tree low = CASE_LOW (elt); tree low = CASE_LOW (elt);
tree high = CASE_HIGH (elt);
bool remove_element = FALSE; bool remove_element = FALSE;
if (low) if (low)
{ {
/* Discard empty ranges. */ gcc_checking_assert (TREE_CODE (low) == INTEGER_CST);
tree high = CASE_HIGH (elt); gcc_checking_assert (!high || TREE_CODE (high) == INTEGER_CST);
if (high && tree_int_cst_lt (high, low))
/* This is a non-default case label, i.e. it has a value.
See if the case label is reachable within the range of
the index type. Remove out-of-range case values. Turn
case ranges into a canonical form (high > low strictly)
and convert the case label values to the index type.
NB: The type of gimple_switch_index() may be the promoted
type, but the case labels retain the original type. */
if (high)
{
/* This is a case range. Discard empty ranges.
If the bounds or the range are equal, turn this
into a simple (one-value) case. */
int cmp = tree_int_cst_compare (high, low);
if (cmp < 0)
remove_element = TRUE;
else if (cmp == 0)
high = NULL_TREE;
}
if (! high)
{
/* If the simple case value is unreachable, ignore it. */
if ((TREE_CODE (min_value) == INTEGER_CST
&& tree_int_cst_compare (low, min_value) < 0)
|| (TREE_CODE (max_value) == INTEGER_CST
&& tree_int_cst_compare (low, max_value) > 0))
remove_element = TRUE; remove_element = TRUE;
else
low = fold_convert (index_type, low);
}
else
{
/* If the entire case range is unreachable, ignore it. */
if ((TREE_CODE (min_value) == INTEGER_CST
&& tree_int_cst_compare (high, min_value) < 0)
|| (TREE_CODE (max_value) == INTEGER_CST
&& tree_int_cst_compare (low, max_value) > 0))
remove_element = TRUE;
else
{
/* If the lower bound is less than the index type's
minimum value, truncate the range bounds. */
if (TREE_CODE (min_value) == INTEGER_CST
&& tree_int_cst_compare (low, min_value) < 0)
low = min_value;
low = fold_convert (index_type, low);
/* If the upper bound is greater than the index type's
maximum value, truncate the range bounds. */
if (TREE_CODE (max_value) == INTEGER_CST
&& tree_int_cst_compare (high, max_value) > 0)
high = max_value;
high = fold_convert (index_type, high);
}
}
CASE_LOW (elt) = low;
CASE_HIGH (elt) = high;
} }
else else
{ {
...@@ -1636,25 +1705,20 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p) ...@@ -1636,25 +1705,20 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
if (!default_case) if (!default_case)
{ {
tree type = TREE_TYPE (switch_expr);
/* If the switch has no default label, add one, so that we jump /* If the switch has no default label, add one, so that we jump
around the switch body. If the labels already cover the whole around the switch body. If the labels already cover the whole
range of type, add the default label pointing to one of the range of the switch index_type, add the default label pointing
existing labels. */ to one of the existing labels. */
if (type == void_type_node)
type = TREE_TYPE (SWITCH_COND (switch_expr));
if (len if (len
&& INTEGRAL_TYPE_P (type) && TYPE_MIN_VALUE (index_type)
&& TYPE_MIN_VALUE (type) && TYPE_MAX_VALUE (index_type)
&& TYPE_MAX_VALUE (type)
&& tree_int_cst_equal (CASE_LOW (VEC_index (tree, labels, 0)), && tree_int_cst_equal (CASE_LOW (VEC_index (tree, labels, 0)),
TYPE_MIN_VALUE (type))) TYPE_MIN_VALUE (index_type)))
{ {
tree low, high = CASE_HIGH (VEC_index (tree, labels, len - 1)); tree low, high = CASE_HIGH (VEC_index (tree, labels, len - 1));
if (!high) if (!high)
high = CASE_LOW (VEC_index (tree, labels, len - 1)); high = CASE_LOW (VEC_index (tree, labels, len - 1));
if (tree_int_cst_equal (high, TYPE_MAX_VALUE (type))) if (tree_int_cst_equal (high, TYPE_MAX_VALUE (index_type)))
{ {
for (i = 1; i < len; i++) for (i = 1; i < len; i++)
{ {
......
2012-04-18 Steven Bosscher <steven@gcc.gnu.org>
* go-gcc.cc (Gcc_backend::switch_statement): Build SWITCH_EXPR
with NULL_TREE type instead of void_type_node.
2012-03-09 Ian Lance Taylor <iant@google.com> 2012-03-09 Ian Lance Taylor <iant@google.com>
* go-gcc.cc (Gcc_backend::assignment_statement): Convert the rhs * go-gcc.cc (Gcc_backend::assignment_statement): Convert the rhs
......
...@@ -1087,7 +1087,7 @@ Gcc_backend::switch_statement( ...@@ -1087,7 +1087,7 @@ Gcc_backend::switch_statement(
if (tv == error_mark_node) if (tv == error_mark_node)
return this->error_statement(); return this->error_statement();
tree t = build3_loc(switch_location.gcc_location(), SWITCH_EXPR, tree t = build3_loc(switch_location.gcc_location(), SWITCH_EXPR,
void_type_node, tv, stmt_list, NULL_TREE); NULL_TREE, tv, stmt_list, NULL_TREE);
return this->make_statement(t); return this->make_statement(t);
} }
......
...@@ -1822,66 +1822,25 @@ expand_stack_restore (tree var) ...@@ -1822,66 +1822,25 @@ expand_stack_restore (tree var)
fed to us in descending order from the sorted vector of case labels used fed to us in descending order from the sorted vector of case labels used
in the tree part of the middle end. So the list we construct is in the tree part of the middle end. So the list we construct is
sorted in ascending order. The bounds on the case range, LOW and HIGH, sorted in ascending order. The bounds on the case range, LOW and HIGH,
are converted to case's index type TYPE. */ are converted to case's index type TYPE. Note that the original type
of the case index in the source code is usually "lost" during
gimplification due to type promotion, but the case labels retain the
original type. */
static struct case_node * static struct case_node *
add_case_node (struct case_node *head, tree type, tree low, tree high, add_case_node (struct case_node *head, tree type, tree low, tree high,
tree label, alloc_pool case_node_pool) tree label, alloc_pool case_node_pool)
{ {
tree min_value, max_value;
struct case_node *r; struct case_node *r;
gcc_assert (TREE_CODE (low) == INTEGER_CST); gcc_checking_assert (low);
gcc_assert (!high || TREE_CODE (high) == INTEGER_CST); gcc_checking_assert (! high || (TREE_TYPE (low) == TREE_TYPE (high)));
min_value = TYPE_MIN_VALUE (type);
max_value = TYPE_MAX_VALUE (type);
/* If there's no HIGH value, then this is not a case range; it's
just a simple case label. But that's just a degenerate case
range.
If the bounds are equal, turn this into the one-value case. */
if (!high || tree_int_cst_equal (low, high))
{
/* If the simple case value is unreachable, ignore it. */
if ((TREE_CODE (min_value) == INTEGER_CST
&& tree_int_cst_compare (low, min_value) < 0)
|| (TREE_CODE (max_value) == INTEGER_CST
&& tree_int_cst_compare (low, max_value) > 0))
return head;
low = fold_convert (type, low);
high = low;
}
else
{
/* If the entire case range is unreachable, ignore it. */
if ((TREE_CODE (min_value) == INTEGER_CST
&& tree_int_cst_compare (high, min_value) < 0)
|| (TREE_CODE (max_value) == INTEGER_CST
&& tree_int_cst_compare (low, max_value) > 0))
return head;
/* If the lower bound is less than the index type's minimum
value, truncate the range bounds. */
if (TREE_CODE (min_value) == INTEGER_CST
&& tree_int_cst_compare (low, min_value) < 0)
low = min_value;
low = fold_convert (type, low);
/* If the upper bound is greater than the index type's maximum
value, truncate the range bounds. */
if (TREE_CODE (max_value) == INTEGER_CST
&& tree_int_cst_compare (high, max_value) > 0)
high = max_value;
high = fold_convert (type, high);
}
/* Add this label to the chain. Make sure to drop overflow flags. */ /* Add this label to the chain. Make sure to drop overflow flags. */
r = (struct case_node *) pool_alloc (case_node_pool); r = (struct case_node *) pool_alloc (case_node_pool);
r->low = build_int_cst_wide (TREE_TYPE (low), TREE_INT_CST_LOW (low), r->low = build_int_cst_wide (type, TREE_INT_CST_LOW (low),
TREE_INT_CST_HIGH (low)); TREE_INT_CST_HIGH (low));
r->high = build_int_cst_wide (TREE_TYPE (high), TREE_INT_CST_LOW (high), r->high = build_int_cst_wide (type, TREE_INT_CST_LOW (high),
TREE_INT_CST_HIGH (high)); TREE_INT_CST_HIGH (high));
r->code_label = label; r->code_label = label;
r->parent = r->left = NULL; r->parent = r->left = NULL;
...@@ -2151,9 +2110,12 @@ expand_case (gimple stmt) ...@@ -2151,9 +2110,12 @@ expand_case (gimple stmt)
gcc_assert (low); gcc_assert (low);
high = CASE_HIGH (elt); high = CASE_HIGH (elt);
/* Discard empty ranges. */ /* The canonical from of a case label in GIMPLE is that a simple case
if (high && tree_int_cst_lt (high, low)) has an empty CASE_HIGH. For the casesi and tablejump expanders,
continue; the back ends want simple cases to have high == low. */
gcc_assert (! high || tree_int_cst_lt (low, high));
if (! high)
high = low;
case_list = add_case_node (case_list, index_type, low, high, case_list = add_case_node (case_list, index_type, low, high,
CASE_LABEL (elt), case_node_pool); CASE_LABEL (elt), case_node_pool);
...@@ -2199,16 +2161,10 @@ expand_case (gimple stmt) ...@@ -2199,16 +2161,10 @@ expand_case (gimple stmt)
BITMAP_FREE (label_bitmap); BITMAP_FREE (label_bitmap);
/* cleanup_tree_cfg removes all SWITCH_EXPR with a single /* cleanup_tree_cfg removes all SWITCH_EXPR with a single
destination, such as one with a default case only. However, destination, such as one with a default case only.
it doesn't remove cases that are out of range for the switch It also removes cases that are out of range for the switch
type, so we may still get a zero here. */ type, so we should never get a zero here. */
if (count == 0) gcc_assert (count > 0);
{
if (default_label)
emit_jump (default_label);
free_alloc_pool (case_node_pool);
return;
}
/* Compute span of values. */ /* Compute span of values. */
range = fold_build2 (MINUS_EXPR, index_type, maxval, minval); range = fold_build2 (MINUS_EXPR, index_type, maxval, minval);
......
...@@ -1200,7 +1200,8 @@ default_target_can_inline_p (tree caller, tree callee) ...@@ -1200,7 +1200,8 @@ default_target_can_inline_p (tree caller, tree callee)
this means extra overhead for dispatch tables, which raises the this means extra overhead for dispatch tables, which raises the
threshold for using them. */ threshold for using them. */
unsigned int default_case_values_threshold (void) unsigned int
default_case_values_threshold (void)
{ {
return (HAVE_casesi ? 4 : 5); return (HAVE_casesi ? 4 : 5);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment