mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
474ffc723e
commit
0cd2402db7
|
@ -1,3 +1,12 @@
|
|||
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>
|
||||
|
||||
* cgraph.h (verify_symtab, verify_symtab_node, verify_symtab_base):
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
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>
|
||||
|
||||
PR fortran/52864
|
||||
|
|
|
@ -4749,7 +4749,8 @@ gfc_trans_entry_master_switch (gfc_entry_list * el)
|
|||
tmp = gfc_finish_block (&block);
|
||||
/* The first argument selects the entry point. */
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -882,7 +882,8 @@ io_result (stmtblock_t * block, tree var, gfc_st_label * err_label,
|
|||
rc, build_int_cst (TREE_TYPE (rc),
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -1918,7 +1918,8 @@ gfc_trans_integer_select (gfc_code * code)
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
tmp = build1_v (LABEL_EXPR, end_label);
|
||||
|
@ -2203,7 +2204,8 @@ gfc_trans_character_select (gfc_code *code)
|
|||
gfc_add_block_to_block (&block, &expr1se.post);
|
||||
|
||||
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);
|
||||
|
||||
tmp = build1_v (LABEL_EXPR, end_label);
|
||||
|
@ -2349,7 +2351,8 @@ gfc_trans_character_select (gfc_code *code)
|
|||
gfc_add_block_to_block (&block, &expr1se.post);
|
||||
|
||||
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);
|
||||
|
||||
tmp = build1_v (LABEL_EXPR, end_label);
|
||||
|
|
|
@ -1575,6 +1575,10 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
|
|||
tree switch_expr = *expr_p;
|
||||
gimple_seq switch_body_seq = NULL;
|
||||
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,
|
||||
fb_rvalue);
|
||||
|
@ -1585,6 +1589,7 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
|
|||
{
|
||||
VEC (tree,heap) *labels;
|
||||
VEC (tree,heap) *saved_labels;
|
||||
tree min_value, max_value;
|
||||
tree default_case = NULL_TREE;
|
||||
size_t i, len;
|
||||
gimple gimple_switch;
|
||||
|
@ -1593,7 +1598,7 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
|
|||
be bothered to null out the body too. */
|
||||
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. */
|
||||
saved_labels = gimplify_ctxp->case_labels;
|
||||
gimplify_ctxp->case_labels = VEC_alloc (tree, heap, 8);
|
||||
|
@ -1603,18 +1608,82 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
|
|||
gimplify_ctxp->case_labels = saved_labels;
|
||||
|
||||
i = 0;
|
||||
min_value = TYPE_MIN_VALUE (index_type);
|
||||
max_value = TYPE_MAX_VALUE (index_type);
|
||||
while (i < VEC_length (tree, labels))
|
||||
{
|
||||
tree elt = VEC_index (tree, labels, i);
|
||||
tree low = CASE_LOW (elt);
|
||||
tree high = CASE_HIGH (elt);
|
||||
bool remove_element = FALSE;
|
||||
|
||||
|
||||
if (low)
|
||||
{
|
||||
/* Discard empty ranges. */
|
||||
tree high = CASE_HIGH (elt);
|
||||
if (high && tree_int_cst_lt (high, low))
|
||||
remove_element = TRUE;
|
||||
gcc_checking_assert (TREE_CODE (low) == INTEGER_CST);
|
||||
gcc_checking_assert (!high || TREE_CODE (high) == INTEGER_CST);
|
||||
|
||||
/* 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;
|
||||
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
|
||||
{
|
||||
|
@ -1636,25 +1705,20 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
|
|||
|
||||
if (!default_case)
|
||||
{
|
||||
tree type = TREE_TYPE (switch_expr);
|
||||
|
||||
/* If the switch has no default label, add one, so that we jump
|
||||
around the switch body. If the labels already cover the whole
|
||||
range of type, add the default label pointing to one of the
|
||||
existing labels. */
|
||||
if (type == void_type_node)
|
||||
type = TREE_TYPE (SWITCH_COND (switch_expr));
|
||||
range of the switch index_type, add the default label pointing
|
||||
to one of the existing labels. */
|
||||
if (len
|
||||
&& INTEGRAL_TYPE_P (type)
|
||||
&& TYPE_MIN_VALUE (type)
|
||||
&& TYPE_MAX_VALUE (type)
|
||||
&& TYPE_MIN_VALUE (index_type)
|
||||
&& TYPE_MAX_VALUE (index_type)
|
||||
&& 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));
|
||||
if (!high)
|
||||
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++)
|
||||
{
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
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>
|
||||
|
||||
* go-gcc.cc (Gcc_backend::assignment_statement): Convert the rhs
|
||||
|
|
|
@ -1087,7 +1087,7 @@ Gcc_backend::switch_statement(
|
|||
if (tv == error_mark_node)
|
||||
return this->error_statement();
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
80
gcc/stmt.c
80
gcc/stmt.c
|
@ -1822,66 +1822,25 @@ expand_stack_restore (tree var)
|
|||
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
|
||||
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 *
|
||||
add_case_node (struct case_node *head, tree type, tree low, tree high,
|
||||
tree label, alloc_pool case_node_pool)
|
||||
{
|
||||
tree min_value, max_value;
|
||||
struct case_node *r;
|
||||
|
||||
gcc_assert (TREE_CODE (low) == INTEGER_CST);
|
||||
gcc_assert (!high || TREE_CODE (high) == INTEGER_CST);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
gcc_checking_assert (low);
|
||||
gcc_checking_assert (! high || (TREE_TYPE (low) == TREE_TYPE (high)));
|
||||
|
||||
/* Add this label to the chain. Make sure to drop overflow flags. */
|
||||
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));
|
||||
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));
|
||||
r->code_label = label;
|
||||
r->parent = r->left = NULL;
|
||||
|
@ -2151,9 +2110,12 @@ expand_case (gimple stmt)
|
|||
gcc_assert (low);
|
||||
high = CASE_HIGH (elt);
|
||||
|
||||
/* Discard empty ranges. */
|
||||
if (high && tree_int_cst_lt (high, low))
|
||||
continue;
|
||||
/* The canonical from of a case label in GIMPLE is that a simple case
|
||||
has an empty CASE_HIGH. For the casesi and tablejump expanders,
|
||||
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_LABEL (elt), case_node_pool);
|
||||
|
@ -2199,16 +2161,10 @@ expand_case (gimple stmt)
|
|||
BITMAP_FREE (label_bitmap);
|
||||
|
||||
/* cleanup_tree_cfg removes all SWITCH_EXPR with a single
|
||||
destination, such as one with a default case only. However,
|
||||
it doesn't remove cases that are out of range for the switch
|
||||
type, so we may still get a zero here. */
|
||||
if (count == 0)
|
||||
{
|
||||
if (default_label)
|
||||
emit_jump (default_label);
|
||||
free_alloc_pool (case_node_pool);
|
||||
return;
|
||||
}
|
||||
destination, such as one with a default case only.
|
||||
It also removes cases that are out of range for the switch
|
||||
type, so we should never get a zero here. */
|
||||
gcc_assert (count > 0);
|
||||
|
||||
/* Compute span of values. */
|
||||
range = fold_build2 (MINUS_EXPR, index_type, maxval, minval);
|
||||
|
|
|
@ -1200,7 +1200,8 @@ default_target_can_inline_p (tree caller, tree callee)
|
|||
this means extra overhead for dispatch tables, which raises the
|
||||
threshold for using them. */
|
||||
|
||||
unsigned int default_case_values_threshold (void)
|
||||
unsigned int
|
||||
default_case_values_threshold (void)
|
||||
{
|
||||
return (HAVE_casesi ? 4 : 5);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue