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
This commit is contained in:
parent
6cd83bec4b
commit
4e3e8a5f81
@ -1,3 +1,17 @@
|
||||
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>
|
||||
|
||||
PR tree-optimization/81196
|
||||
|
@ -1675,7 +1675,7 @@ cleanup_dead_labels (void)
|
||||
the ones jumping to the same label.
|
||||
Eg. three separate entries 1: 2: 3: become one entry 1..3: */
|
||||
|
||||
void
|
||||
bool
|
||||
group_case_labels_stmt (gswitch *stmt)
|
||||
{
|
||||
int old_size = gimple_switch_num_labels (stmt);
|
||||
@ -1759,23 +1759,27 @@ group_case_labels_stmt (gswitch *stmt)
|
||||
|
||||
gcc_assert (new_size <= old_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),
|
||||
and scan the sorted vector of cases. Combine the ones jumping to the
|
||||
same label. */
|
||||
|
||||
void
|
||||
bool
|
||||
group_case_labels (void)
|
||||
{
|
||||
basic_block bb;
|
||||
bool changed = false;
|
||||
|
||||
FOR_EACH_BB_FN (bb, cfun)
|
||||
{
|
||||
gimple *stmt = last_stmt (bb);
|
||||
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. */
|
||||
@ -2243,15 +2247,8 @@ find_taken_edge (basic_block bb, tree val)
|
||||
|
||||
stmt = last_stmt (bb);
|
||||
|
||||
gcc_assert (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)
|
||||
return find_taken_edge_cond_expr (bb, 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
|
||||
appear inside an ADDR_EXPR, but we also allow the LABEL_REF to
|
||||
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)
|
||||
return find_taken_edge_computed_goto (bb, TREE_OPERAND (val, 0));
|
||||
return NULL;
|
||||
@ -2304,9 +2302,12 @@ find_taken_edge_cond_expr (basic_block bb, tree val)
|
||||
{
|
||||
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);
|
||||
|
||||
gcc_assert (TREE_CODE (val) == INTEGER_CST);
|
||||
return (integer_zerop (val) ? false_edge : true_edge);
|
||||
}
|
||||
|
||||
@ -2322,7 +2323,12 @@ find_taken_edge_switch_expr (gswitch *switch_stmt, basic_block bb,
|
||||
edge e;
|
||||
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));
|
||||
|
||||
e = find_edge (bb, dest_bb);
|
||||
|
@ -36,8 +36,8 @@ extern void end_recording_case_labels (void);
|
||||
extern basic_block label_to_block_fn (struct function *, tree);
|
||||
#define label_to_block(t) (label_to_block_fn (cfun, t))
|
||||
extern void cleanup_dead_labels (void);
|
||||
extern void group_case_labels_stmt (gswitch *);
|
||||
extern void group_case_labels (void);
|
||||
extern bool group_case_labels_stmt (gswitch *);
|
||||
extern bool group_case_labels (void);
|
||||
extern void replace_uses_by (tree, tree);
|
||||
extern basic_block single_noncomplex_succ (basic_block bb);
|
||||
extern void notice_special_calls (gcall *);
|
||||
|
@ -1205,7 +1205,8 @@ execute_cleanup_cfg_post_optimizing (void)
|
||||
}
|
||||
maybe_remove_unreachable_handlers ();
|
||||
cleanup_dead_labels ();
|
||||
group_case_labels ();
|
||||
if (group_case_labels ())
|
||||
todo |= TODO_cleanup_cfg;
|
||||
if ((flag_compare_debug_opt || flag_compare_debug)
|
||||
&& flag_dump_final_insns)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user