Commit 4e3e8a5f by Richard Biener Committed by Richard Biener

tree-cfg.c (group_case_labels_stmt): Return whether we changed anything.

2017-06-29  Richard Biener  <rguenther@suse.de>

	* tree-cfg.c (group_case_labels_stmt): Return whether we changed
	anything.
	(group_case_labels): Likewise.
	(find_taken_edge): Push sanity checking on val to workers...
	(find_taken_edge_cond_expr): ... here
	(find_taken_edge_switch_expr): ... and here, handle cases
	with just a default label.
	* tree-cfg.h (group_case_labels_stmt): Adjust prototype.
	(group_case_labels): Likewise.
	* tree-cfgcleanup.c (execute_cleanup_cfg_post_optimizing): When
	group_case_labels does anything cleanup the CFG again.

From-SVN: r249780
parent 6cd83bec
2017-06-29 Richard Biener <rguenther@suse.de>
* tree-cfg.c (group_case_labels_stmt): Return whether we changed
anything.
(group_case_labels): Likewise.
(find_taken_edge): Push sanity checking on val to workers...
(find_taken_edge_cond_expr): ... here
(find_taken_edge_switch_expr): ... and here, handle cases
with just a default label.
* tree-cfg.h (group_case_labels_stmt): Adjust prototype.
(group_case_labels): Likewise.
* tree-cfgcleanup.c (execute_cleanup_cfg_post_optimizing): When
group_case_labels does anything cleanup the CFG again.
2017-06-29 Bin Cheng <bin.cheng@arm.com> 2017-06-29 Bin Cheng <bin.cheng@arm.com>
PR tree-optimization/81196 PR tree-optimization/81196
......
...@@ -1675,7 +1675,7 @@ cleanup_dead_labels (void) ...@@ -1675,7 +1675,7 @@ cleanup_dead_labels (void)
the ones jumping to the same label. the ones jumping to the same label.
Eg. three separate entries 1: 2: 3: become one entry 1..3: */ Eg. three separate entries 1: 2: 3: become one entry 1..3: */
void bool
group_case_labels_stmt (gswitch *stmt) group_case_labels_stmt (gswitch *stmt)
{ {
int old_size = gimple_switch_num_labels (stmt); int old_size = gimple_switch_num_labels (stmt);
...@@ -1759,23 +1759,27 @@ group_case_labels_stmt (gswitch *stmt) ...@@ -1759,23 +1759,27 @@ group_case_labels_stmt (gswitch *stmt)
gcc_assert (new_size <= old_size); gcc_assert (new_size <= old_size);
gimple_switch_set_num_labels (stmt, new_size); gimple_switch_set_num_labels (stmt, new_size);
return new_size < old_size;
} }
/* Look for blocks ending in a multiway branch (a GIMPLE_SWITCH), /* Look for blocks ending in a multiway branch (a GIMPLE_SWITCH),
and scan the sorted vector of cases. Combine the ones jumping to the and scan the sorted vector of cases. Combine the ones jumping to the
same label. */ same label. */
void bool
group_case_labels (void) group_case_labels (void)
{ {
basic_block bb; basic_block bb;
bool changed = false;
FOR_EACH_BB_FN (bb, cfun) FOR_EACH_BB_FN (bb, cfun)
{ {
gimple *stmt = last_stmt (bb); gimple *stmt = last_stmt (bb);
if (stmt && gimple_code (stmt) == GIMPLE_SWITCH) if (stmt && gimple_code (stmt) == GIMPLE_SWITCH)
group_case_labels_stmt (as_a <gswitch *> (stmt)); changed |= group_case_labels_stmt (as_a <gswitch *> (stmt));
} }
return changed;
} }
/* Checks whether we can merge block B into block A. */ /* Checks whether we can merge block B into block A. */
...@@ -2243,15 +2247,8 @@ find_taken_edge (basic_block bb, tree val) ...@@ -2243,15 +2247,8 @@ find_taken_edge (basic_block bb, tree val)
stmt = last_stmt (bb); stmt = last_stmt (bb);
gcc_assert (stmt);
gcc_assert (is_ctrl_stmt (stmt)); gcc_assert (is_ctrl_stmt (stmt));
if (val == NULL)
return NULL;
if (!is_gimple_min_invariant (val))
return NULL;
if (gimple_code (stmt) == GIMPLE_COND) if (gimple_code (stmt) == GIMPLE_COND)
return find_taken_edge_cond_expr (bb, val); return find_taken_edge_cond_expr (bb, val);
...@@ -2266,7 +2263,8 @@ find_taken_edge (basic_block bb, tree val) ...@@ -2266,7 +2263,8 @@ find_taken_edge (basic_block bb, tree val)
It may be the case that we only need to allow the LABEL_REF to It may be the case that we only need to allow the LABEL_REF to
appear inside an ADDR_EXPR, but we also allow the LABEL_REF to appear inside an ADDR_EXPR, but we also allow the LABEL_REF to
appear inside a LABEL_EXPR just to be safe. */ appear inside a LABEL_EXPR just to be safe. */
if ((TREE_CODE (val) == ADDR_EXPR || TREE_CODE (val) == LABEL_EXPR) if (val
&& (TREE_CODE (val) == ADDR_EXPR || TREE_CODE (val) == LABEL_EXPR)
&& TREE_CODE (TREE_OPERAND (val, 0)) == LABEL_DECL) && TREE_CODE (TREE_OPERAND (val, 0)) == LABEL_DECL)
return find_taken_edge_computed_goto (bb, TREE_OPERAND (val, 0)); return find_taken_edge_computed_goto (bb, TREE_OPERAND (val, 0));
return NULL; return NULL;
...@@ -2304,9 +2302,12 @@ find_taken_edge_cond_expr (basic_block bb, tree val) ...@@ -2304,9 +2302,12 @@ find_taken_edge_cond_expr (basic_block bb, tree val)
{ {
edge true_edge, false_edge; edge true_edge, false_edge;
if (val == NULL
|| TREE_CODE (val) != INTEGER_CST)
return NULL;
extract_true_false_edges_from_block (bb, &true_edge, &false_edge); extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
gcc_assert (TREE_CODE (val) == INTEGER_CST);
return (integer_zerop (val) ? false_edge : true_edge); return (integer_zerop (val) ? false_edge : true_edge);
} }
...@@ -2322,7 +2323,12 @@ find_taken_edge_switch_expr (gswitch *switch_stmt, basic_block bb, ...@@ -2322,7 +2323,12 @@ find_taken_edge_switch_expr (gswitch *switch_stmt, basic_block bb,
edge e; edge e;
tree taken_case; tree taken_case;
taken_case = find_case_label_for_value (switch_stmt, val); if (gimple_switch_num_labels (switch_stmt) == 1)
taken_case = gimple_switch_default_label (switch_stmt);
else if (! val || TREE_CODE (val) != INTEGER_CST)
return NULL;
else
taken_case = find_case_label_for_value (switch_stmt, val);
dest_bb = label_to_block (CASE_LABEL (taken_case)); dest_bb = label_to_block (CASE_LABEL (taken_case));
e = find_edge (bb, dest_bb); e = find_edge (bb, dest_bb);
......
...@@ -36,8 +36,8 @@ extern void end_recording_case_labels (void); ...@@ -36,8 +36,8 @@ extern void end_recording_case_labels (void);
extern basic_block label_to_block_fn (struct function *, tree); extern basic_block label_to_block_fn (struct function *, tree);
#define label_to_block(t) (label_to_block_fn (cfun, t)) #define label_to_block(t) (label_to_block_fn (cfun, t))
extern void cleanup_dead_labels (void); extern void cleanup_dead_labels (void);
extern void group_case_labels_stmt (gswitch *); extern bool group_case_labels_stmt (gswitch *);
extern void group_case_labels (void); extern bool group_case_labels (void);
extern void replace_uses_by (tree, tree); extern void replace_uses_by (tree, tree);
extern basic_block single_noncomplex_succ (basic_block bb); extern basic_block single_noncomplex_succ (basic_block bb);
extern void notice_special_calls (gcall *); extern void notice_special_calls (gcall *);
......
...@@ -1205,7 +1205,8 @@ execute_cleanup_cfg_post_optimizing (void) ...@@ -1205,7 +1205,8 @@ execute_cleanup_cfg_post_optimizing (void)
} }
maybe_remove_unreachable_handlers (); maybe_remove_unreachable_handlers ();
cleanup_dead_labels (); cleanup_dead_labels ();
group_case_labels (); if (group_case_labels ())
todo |= TODO_cleanup_cfg;
if ((flag_compare_debug_opt || flag_compare_debug) if ((flag_compare_debug_opt || flag_compare_debug)
&& flag_dump_final_insns) && flag_dump_final_insns)
{ {
......
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