From 4e3e8a5f8175d06b2de55a6f45491fc484901370 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 29 Jun 2017 11:25:29 +0000 Subject: [PATCH] tree-cfg.c (group_case_labels_stmt): Return whether we changed anything. 2017-06-29 Richard Biener * 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 --- gcc/ChangeLog | 14 ++++++++++++++ gcc/tree-cfg.c | 32 +++++++++++++++++++------------- gcc/tree-cfg.h | 4 ++-- gcc/tree-cfgcleanup.c | 3 ++- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bed5b90f868..578068bd343 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2017-06-29 Richard Biener + + * 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 PR tree-optimization/81196 diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 589508df044..e82f95b48dd 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -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 (stmt)); + changed |= group_case_labels_stmt (as_a (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); diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h index a0ef479ef20..4e1b5b076d5 100644 --- a/gcc/tree-cfg.h +++ b/gcc/tree-cfg.h @@ -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 *); diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c index 8bb5e237395..c904d0cf57f 100644 --- a/gcc/tree-cfgcleanup.c +++ b/gcc/tree-cfgcleanup.c @@ -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) { -- 2.30.2