Hi. There's updated version with notes that were discussed with Richi on IRC. As pointed out label_to_block can potentially lead to quadratic complexity, but it's not ambition of the patch to resolve that.
Martin
>From 393a0b87d7d667f0db6e512a840f2da3f51c8f7b Mon Sep 17 00:00:00 2001 From: marxin <mli...@suse.cz> Date: Fri, 3 Aug 2018 14:54:32 +0200 Subject: [PATCH] Add new gswitch related functions into tree-cfg.c. gcc/ChangeLog: 2018-08-23 Martin Liska <mli...@suse.cz> * cfgexpand.c (expand_asm_stmt): Use label_to_block instead of label_to_block_fn. * hsa-gen.c (gen_hsa_insns_for_switch_stmt): Use new function gimple_switch_default_bb. (convert_switch_statements): Use cfun directly and use label_to_block. (expand_builtins): Use cfun directly. * ipa-fnsummary.c (set_switch_stmt_execution_predicate): Use new function gimple_switch_edge. * stmt.c (label_to_block_fn): Remove declaration. (expand_case): Use label_to_block. * tree-cfg.c (make_gimple_switch_edges): Use new function gimple_switch_bb. (group_case_labels_stmt): Use gimple_switch_default_bb. (gimple_verify_flow_info): Use gimple_switch_bb. (gimple_switch_bb): New. (gimple_switch_default_bb): Likewise. (gimple_switch_edge): Likewise. (gimple_switch_default_edge): Likewise. * tree-cfg.h (label_to_block): Make proper extern symbol. (gimple_switch_bb): New. (gimple_switch_default_bb): Likewise. (gimple_switch_edge): Likewise. (gimple_switch_default_edge): Likewise. * tree-cfgcleanup.c (convert_single_case_switch): Use gimple_switch_default_bb. * tree-switch-conversion.c (switch_conversion::collect): Use gimple_switch_default_edge and gimple_switch_edge functions. (switch_conversion::check_final_bb): Use gimple_switch_bb. (switch_decision_tree::compute_cases_per_edge): Use gimple_switch_edge. (switch_decision_tree::analyze_switch_statement): Do not use label_to_block_fn. (switch_decision_tree::try_switch_expansion): Use gimple_switch_default_edge. --- gcc/cfgexpand.c | 2 +- gcc/hsa-gen.c | 21 ++++++---------- gcc/ipa-fnsummary.c | 2 +- gcc/stmt.c | 4 +--- gcc/tree-cfg.c | 46 ++++++++++++++++++++++++++++++------ gcc/tree-cfg.h | 4 ++++ gcc/tree-cfgcleanup.c | 5 ++-- gcc/tree-switch-conversion.c | 40 ++++++++++--------------------- 8 files changed, 68 insertions(+), 56 deletions(-) diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 3c5b30b79f8..156a529d730 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -3239,7 +3239,7 @@ expand_asm_stmt (gasm *stmt) may insert further instructions into the same basic block after asm goto and if we don't do this, insertion of instructions on the fallthru edge might misbehave. See PR58670. */ - if (fallthru_bb && label_to_block_fn (cfun, label) == fallthru_bb) + if (fallthru_bb && label_to_block (label) == fallthru_bb) { if (fallthru_label == NULL_RTX) fallthru_label = gen_label_rtx (); diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c index 6595bedac82..39bd42e4522 100644 --- a/gcc/hsa-gen.c +++ b/gcc/hsa-gen.c @@ -3475,7 +3475,6 @@ gen_hsa_insns_for_switch_stmt (gswitch *s, hsa_bb *hbb) e->flags &= ~EDGE_FALLTHRU; e->flags |= EDGE_TRUE_VALUE; - function *func = DECL_STRUCT_FUNCTION (current_function_decl); tree index_tree = gimple_switch_index (s); tree lowest = get_switch_low (s); tree highest = get_switch_high (s); @@ -3499,9 +3498,7 @@ gen_hsa_insns_for_switch_stmt (gswitch *s, hsa_bb *hbb) hbb->append_insn (new hsa_insn_cbr (cmp_reg)); - tree default_label = gimple_switch_default_label (s); - basic_block default_label_bb = label_to_block_fn (func, - CASE_LABEL (default_label)); + basic_block default_label_bb = gimple_switch_default_bb (s); if (!gimple_seq_empty_p (phi_nodes (default_label_bb))) { @@ -3536,7 +3533,7 @@ gen_hsa_insns_for_switch_stmt (gswitch *s, hsa_bb *hbb) for (unsigned i = 1; i < labels; i++) { tree label = gimple_switch_label (s, i); - basic_block bb = label_to_block_fn (func, CASE_LABEL (label)); + basic_block bb = label_to_block (CASE_LABEL (label)); unsigned HOST_WIDE_INT sub_low = tree_to_uhwi (int_const_binop (MINUS_EXPR, CASE_LOW (label), lowest)); @@ -6290,12 +6287,11 @@ LD: hard_work_3 (); static bool convert_switch_statements (void) { - function *func = DECL_STRUCT_FUNCTION (current_function_decl); basic_block bb; bool modified_cfg = false; - FOR_EACH_BB_FN (bb, func) + FOR_EACH_BB_FN (bb, cfun) { gimple_stmt_iterator gsi = gsi_last_bb (bb); if (gsi_end_p (gsi)) @@ -6318,7 +6314,7 @@ convert_switch_statements (void) tree index_type = TREE_TYPE (index); tree default_label = gimple_switch_default_label (s); basic_block default_label_bb - = label_to_block_fn (func, CASE_LABEL (default_label)); + = label_to_block (CASE_LABEL (default_label)); basic_block cur_bb = bb; auto_vec <edge> new_edges; @@ -6330,8 +6326,7 @@ convert_switch_statements (void) should be fixed after we add new collection of edges. */ for (unsigned i = 0; i < labels; i++) { - tree label = gimple_switch_label (s, i); - basic_block label_bb = label_to_block_fn (func, CASE_LABEL (label)); + basic_block label_bb = gimple_switch_bb (s, i); edge e = find_edge (bb, label_bb); edge_counts.safe_push (e->count ()); edge_probabilities.safe_push (e->probability); @@ -6413,8 +6408,7 @@ convert_switch_statements (void) gsi_insert_before (&cond_gsi, c, GSI_SAME_STMT); - basic_block label_bb - = label_to_block_fn (func, CASE_LABEL (label)); + basic_block label_bb = label_to_block (CASE_LABEL (label)); edge new_edge = make_edge (cur_bb, label_bb, EDGE_TRUE_VALUE); profile_probability prob_sum = sum_slice <profile_probability> (edge_probabilities, i, labels, profile_probability::never ()) @@ -6481,10 +6475,9 @@ convert_switch_statements (void) static void expand_builtins () { - function *func = DECL_STRUCT_FUNCTION (current_function_decl); basic_block bb; - FOR_EACH_BB_FN (bb, func) + FOR_EACH_BB_FN (bb, cfun) { for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c index a8fc2c2df9a..8aac26812f6 100644 --- a/gcc/ipa-fnsummary.c +++ b/gcc/ipa-fnsummary.c @@ -1291,7 +1291,7 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi, tree min, max; predicate p; - e = find_edge (bb, label_to_block (CASE_LABEL (cl))); + e = gimple_switch_edge (last, case_idx); min = CASE_LOW (cl); max = CASE_HIGH (cl); diff --git a/gcc/stmt.c b/gcc/stmt.c index b8df1818137..dc443a6fd66 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -82,8 +82,6 @@ struct simple_case_node tree m_code_label; }; -extern basic_block label_to_block_fn (struct function *, tree); - static bool check_unique_operand_names (tree, tree, tree); static char *resolve_operand_name_1 (char *, tree, tree, tree); @@ -907,7 +905,7 @@ expand_case (gswitch *stmt) /* Find the default case target label. */ tree default_lab = CASE_LABEL (gimple_switch_default_label (stmt)); default_label = jump_target_rtx (default_lab); - basic_block default_bb = label_to_block_fn (cfun, default_lab); + basic_block default_bb = label_to_block (default_lab); edge default_edge = find_edge (bb, default_bb); /* Get upper and lower bounds of case values. */ diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 463dd8a3bf9..39157ade8aa 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -1397,8 +1397,7 @@ make_gimple_switch_edges (gswitch *entry, basic_block bb) for (i = 0; i < n; ++i) { - tree lab = CASE_LABEL (gimple_switch_label (entry, i)); - basic_block label_bb = label_to_block (lab); + basic_block label_bb = gimple_switch_bb (entry, i); make_edge (bb, label_bb, 0); } } @@ -1773,7 +1772,7 @@ group_case_labels_stmt (gswitch *stmt) int i, next_index, new_size; basic_block default_bb = NULL; - default_bb = label_to_block (CASE_LABEL (gimple_switch_default_label (stmt))); + default_bb = gimple_switch_default_bb (stmt); /* Look for possible opportunities to merge cases. */ new_size = i = 1; @@ -5655,8 +5654,7 @@ gimple_verify_flow_info (void) /* Mark all the destination basic blocks. */ for (i = 0; i < n; ++i) { - tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i)); - basic_block label_bb = label_to_block (lab); + basic_block label_bb = gimple_switch_bb (switch_stmt, i); gcc_assert (!label_bb->aux || label_bb->aux == (void *)1); label_bb->aux = (void *)1; } @@ -5711,8 +5709,7 @@ gimple_verify_flow_info (void) /* Check that we have all of them. */ for (i = 0; i < n; ++i) { - tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i)); - basic_block label_bb = label_to_block (lab); + basic_block label_bb = gimple_switch_bb (switch_stmt, i); if (label_bb->aux != (void *)2) { @@ -9143,6 +9140,41 @@ generate_range_test (basic_block bb, tree index, tree low, tree high, gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT); } +/* Return the basic block that belongs to label numbered INDEX + of a switch statement. */ + +basic_block +gimple_switch_bb (gswitch *gs, unsigned index) +{ + return label_to_block (CASE_LABEL (gimple_switch_label (gs, index))); +} + +/* Return the default basic block of a switch statement. */ + +basic_block +gimple_switch_default_bb (gswitch *gs) +{ + return gimple_switch_bb (gs, 0); +} + +/* Return the edge that belongs to label numbered INDEX + of a switch statement. */ + +edge +gimple_switch_edge (gswitch *gs, unsigned index) +{ + return find_edge (gimple_bb (gs), gimple_switch_bb (gs, index)); +} + +/* Return the default edge of a switch statement. */ + +edge +gimple_switch_default_edge (gswitch *gs) +{ + return gimple_switch_edge (gs, 0); +} + + /* Emit return warnings. */ namespace { diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h index 9491bb45feb..28194476cd1 100644 --- a/gcc/tree-cfg.h +++ b/gcc/tree-cfg.h @@ -112,6 +112,10 @@ extern bool extract_true_false_controlled_edges (basic_block, basic_block, edge *, edge *); extern void generate_range_test (basic_block bb, tree index, tree low, tree high, tree *lhs, tree *rhs); +extern basic_block gimple_switch_bb (gswitch *gs, unsigned index); +extern basic_block gimple_switch_default_bb (gswitch *gs); +extern edge gimple_switch_edge (gswitch *gs, unsigned index); +extern edge gimple_switch_default_edge (gswitch *gs); /* Return true if the LHS of a call should be removed. */ diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c index b27ba8a7333..adac1d5f487 100644 --- a/gcc/tree-cfgcleanup.c +++ b/gcc/tree-cfgcleanup.c @@ -84,13 +84,12 @@ convert_single_case_switch (gswitch *swtch, gimple_stmt_iterator &gsi) return false; tree index = gimple_switch_index (swtch); - tree default_label = CASE_LABEL (gimple_switch_default_label (swtch)); tree label = gimple_switch_label (swtch, 1); tree low = CASE_LOW (label); tree high = CASE_HIGH (label); - basic_block default_bb = label_to_block_fn (cfun, default_label); - basic_block case_bb = label_to_block_fn (cfun, CASE_LABEL (label)); + basic_block default_bb = gimple_switch_default_bb (swtch); + basic_block case_bb = label_to_block (CASE_LABEL (label)); basic_block bb = gimple_bb (swtch); gcond *cond; diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c index 9a594a01fc4..c3d52fb3e74 100644 --- a/gcc/tree-switch-conversion.c +++ b/gcc/tree-switch-conversion.c @@ -78,7 +78,6 @@ switch_conversion::collect (gswitch *swtch) unsigned int i; edge e, e_default, e_first; edge_iterator ei; - basic_block first; m_switch = swtch; @@ -87,9 +86,8 @@ switch_conversion::collect (gswitch *swtch) Collect the bits we can deduce from the CFG. */ m_index_expr = gimple_switch_index (swtch); m_switch_bb = gimple_bb (swtch); - m_default_bb - = label_to_block (CASE_LABEL (gimple_switch_default_label (swtch))); - e_default = find_edge (m_switch_bb, m_default_bb); + e_default = gimple_switch_default_edge (swtch); + m_default_bb = e_default->dest; m_default_prob = e_default->probability; m_default_count = e_default->count (); FOR_EACH_EDGE (e, ei, m_switch_bb->succs) @@ -120,15 +118,9 @@ switch_conversion::collect (gswitch *swtch) } if (m_contiguous_range) - { - first = label_to_block (CASE_LABEL (gimple_switch_label (swtch, 1))); - e_first = find_edge (m_switch_bb, first); - } + e_first = gimple_switch_edge (swtch, 1); else - { - first = m_default_bb; - e_first = e_default; - } + e_first = e_default; /* See if there is one common successor block for all branch targets. If it exists, record it in FINAL_BB. @@ -306,8 +298,7 @@ switch_conversion::check_final_bb () unsigned int branch_num = gimple_switch_num_labels (m_switch); for (unsigned int i = 1; i < branch_num; i++) { - tree lab = CASE_LABEL (gimple_switch_label (m_switch, i)); - if (label_to_block (lab) == bb) + if (gimple_switch_bb (m_switch, i) == bb) { m_reason = reason; return false; @@ -1577,15 +1568,11 @@ bit_test_cluster::hoist_edge_and_branch_if_true (gimple_stmt_iterator *gsip, void switch_decision_tree::compute_cases_per_edge () { - basic_block bb = gimple_bb (m_switch); reset_out_edges_aux (); int ncases = gimple_switch_num_labels (m_switch); for (int i = ncases - 1; i >= 1; --i) { - tree elt = gimple_switch_label (m_switch, i); - tree lab = CASE_LABEL (elt); - basic_block case_bb = label_to_block_fn (cfun, lab); - edge case_edge = find_edge (bb, case_bb); + edge case_edge = gimple_switch_edge (m_switch, i); case_edge->aux = (void *) ((intptr_t) (case_edge->aux) + 1); } } @@ -1601,8 +1588,7 @@ switch_decision_tree::analyze_switch_statement () auto_vec<cluster *> clusters; clusters.create (l - 1); - tree default_label = CASE_LABEL (gimple_switch_default_label (m_switch)); - basic_block default_bb = label_to_block_fn (cfun, default_label); + basic_block default_bb = gimple_switch_default_bb (m_switch); m_case_bbs.reserve (l); m_case_bbs.quick_push (default_bb); @@ -1612,15 +1598,16 @@ switch_decision_tree::analyze_switch_statement () { tree elt = gimple_switch_label (m_switch, i); tree lab = CASE_LABEL (elt); - basic_block case_bb = label_to_block_fn (cfun, lab); + basic_block case_bb = label_to_block (lab); edge case_edge = find_edge (bb, case_bb); tree low = CASE_LOW (elt); tree high = CASE_HIGH (elt); profile_probability p = case_edge->probability.apply_scale (1, (intptr_t) (case_edge->aux)); - clusters.quick_push (new simple_cluster (low, high, elt, case_bb, p)); - m_case_bbs.quick_push (case_bb); + clusters.quick_push (new simple_cluster (low, high, elt, case_edge->dest, + p)); + m_case_bbs.quick_push (case_edge->dest); } reset_out_edges_aux (); @@ -1694,9 +1681,8 @@ switch_decision_tree::try_switch_expansion (vec<cluster *> &clusters) return false; /* Find the default case target label. */ - tree default_label_expr = CASE_LABEL (gimple_switch_default_label (m_switch)); - m_default_bb = label_to_block_fn (cfun, default_label_expr); - edge default_edge = find_edge (bb, m_default_bb); + edge default_edge = gimple_switch_default_edge (m_switch); + m_default_bb = default_edge->dest; /* Do the insertion of a case label into m_case_list. The labels are fed to us in descending order from the sorted vector of case labels used -- 2.18.0