diff options
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r-- | gcc/tree-cfg.c | 135 |
1 files changed, 78 insertions, 57 deletions
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 589508df044..733c92fcdd0 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -1051,6 +1051,7 @@ gimple_find_sub_bbs (gimple_seq seq, gimple_stmt_iterator *gsi) struct omp_region *cur_region = NULL; profile_count cnt = profile_count::zero (); int freq = 0; + bool all = true; int cur_omp_region_idx = 0; int mer = make_edges_bb (bb, &cur_region, &cur_omp_region_idx); @@ -1061,12 +1062,16 @@ gimple_find_sub_bbs (gimple_seq seq, gimple_stmt_iterator *gsi) edge_iterator ei; FOR_EACH_EDGE (e, ei, bb->preds) { - cnt += e->count; + if (e->count.initialized_p ()) + cnt += e->count; + else + all = false; freq += EDGE_FREQUENCY (e); } - bb->count = cnt; - bb->frequency = freq; tree_guess_outgoing_edge_probabilities (bb); + if (all || profile_status_for_fn (cfun) == PROFILE_READ) + bb->count = cnt; + bb->frequency = freq; FOR_EACH_EDGE (e, ei, bb->succs) e->count = bb->count.apply_probability (e->probability); @@ -1675,17 +1680,17 @@ 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); - int i, j, base_index, new_size = old_size; + int i, next_index, new_size; basic_block default_bb = NULL; default_bb = label_to_block (CASE_LABEL (gimple_switch_default_label (stmt))); /* Look for possible opportunities to merge cases. */ - i = 1; + new_size = i = 1; while (i < old_size) { tree base_case, base_high; @@ -1696,26 +1701,25 @@ group_case_labels_stmt (gswitch *stmt) gcc_assert (base_case); base_bb = label_to_block (CASE_LABEL (base_case)); - /* Discard cases that have the same destination as the default case. */ - if (base_bb == default_bb) + /* Discard cases that have the same destination as the default case or + whose destiniation blocks have already been removed as unreachable. */ + if (base_bb == NULL || base_bb == default_bb) { - gimple_switch_set_label (stmt, i, NULL_TREE); i++; - new_size--; continue; } base_high = CASE_HIGH (base_case) ? CASE_HIGH (base_case) : CASE_LOW (base_case); - base_index = i++; + next_index = i + 1; /* Try to merge case labels. Break out when we reach the end of the label vector or when we cannot merge the next case label with the current one. */ - while (i < old_size) + while (next_index < old_size) { - tree merge_case = gimple_switch_label (stmt, i); + tree merge_case = gimple_switch_label (stmt, next_index); basic_block merge_bb = label_to_block (CASE_LABEL (merge_case)); wide_int bhp1 = wi::add (base_high, 1); @@ -1727,9 +1731,7 @@ group_case_labels_stmt (gswitch *stmt) base_high = CASE_HIGH (merge_case) ? CASE_HIGH (merge_case) : CASE_LOW (merge_case); CASE_HIGH (base_case) = base_high; - gimple_switch_set_label (stmt, i, NULL_TREE); - new_size--; - i++; + next_index++; } else break; @@ -1742,40 +1744,43 @@ group_case_labels_stmt (gswitch *stmt) edge base_edge = find_edge (gimple_bb (stmt), base_bb); if (base_edge != NULL) remove_edge_and_dominated_blocks (base_edge); - gimple_switch_set_label (stmt, base_index, NULL_TREE); - new_size--; + i = next_index; + continue; } - } - /* Compress the case labels in the label vector, and adjust the - length of the vector. */ - for (i = 0, j = 0; i < new_size; i++) - { - while (! gimple_switch_label (stmt, j)) - j++; - gimple_switch_set_label (stmt, i, - gimple_switch_label (stmt, j++)); + if (new_size < i) + gimple_switch_set_label (stmt, new_size, + gimple_switch_label (stmt, i)); + i = next_index; + new_size++; } gcc_assert (new_size <= old_size); - gimple_switch_set_num_labels (stmt, new_size); + + if (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. */ @@ -2077,7 +2082,7 @@ gimple_merge_blocks (basic_block a, basic_block b) profiles. */ if (a->loop_father == b->loop_father) { - a->count = MAX (a->count, b->count); + a->count = a->count.merge (b->count); a->frequency = MAX (a->frequency, b->frequency); } @@ -2243,15 +2248,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 +2264,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 +2303,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 +2324,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); @@ -2837,9 +2844,7 @@ gimple_split_edge (edge edge_in) new_bb = create_empty_bb (after_bb); new_bb->frequency = EDGE_FREQUENCY (edge_in); new_bb->count = edge_in->count; - new_edge = make_edge (new_bb, dest, EDGE_FALLTHRU); - new_edge->probability = REG_BR_PROB_BASE; - new_edge->count = edge_in->count; + new_edge = make_single_succ_edge (new_bb, dest, EDGE_FALLTHRU); e = redirect_edge_and_branch (edge_in, new_bb); gcc_assert (e == edge_in); @@ -3049,7 +3054,9 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) tree t1 = TREE_OPERAND (t, 1); tree t2 = TREE_OPERAND (t, 2); if (!tree_fits_uhwi_p (t1) - || !tree_fits_uhwi_p (t2)) + || !tree_fits_uhwi_p (t2) + || !types_compatible_p (bitsizetype, TREE_TYPE (t1)) + || !types_compatible_p (bitsizetype, TREE_TYPE (t2))) { error ("invalid position or size operand to BIT_FIELD_REF"); return t; @@ -3493,8 +3500,6 @@ verify_gimple_call (gcall *stmt) && !useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (fntype)) /* ??? At least C++ misses conversions at assignments from void * call results. - ??? Java is completely off. Especially with functions - returning java.lang.Object. For now simply allow arbitrary pointer type conversions. */ && !(POINTER_TYPE_P (TREE_TYPE (lhs)) && POINTER_TYPE_P (TREE_TYPE (fntype)))) @@ -4245,6 +4250,7 @@ verify_gimple_assign_ternary (gassign *stmt) return true; } if (! tree_fits_uhwi_p (rhs3) + || ! types_compatible_p (bitsizetype, TREE_TYPE (rhs3)) || ! tree_fits_uhwi_p (TYPE_SIZE (rhs2_type))) { error ("invalid position or size in BIT_INSERT_EXPR"); @@ -6391,9 +6397,9 @@ bb_part_of_region_p (basic_block bb, basic_block* bbs, unsigned n_region) */ bool -gimple_duplicate_sese_tail (edge entry ATTRIBUTE_UNUSED, edge exit ATTRIBUTE_UNUSED, - basic_block *region ATTRIBUTE_UNUSED, unsigned n_region ATTRIBUTE_UNUSED, - basic_block *region_copy ATTRIBUTE_UNUSED) +gimple_duplicate_sese_tail (edge entry, edge exit, + basic_block *region, unsigned n_region, + basic_block *region_copy) { unsigned i; bool free_region_copy = false; @@ -6503,7 +6509,12 @@ gimple_duplicate_sese_tail (edge entry ATTRIBUTE_UNUSED, edge exit ATTRIBUTE_UNU sorig = single_succ_edge (switch_bb); sorig->flags = exits[1]->flags; + sorig->probability = exits[1]->probability; + sorig->count = exits[1]->count; snew = make_edge (switch_bb, nentry_bb, exits[0]->flags); + snew->probability = exits[0]->probability; + snew->count = exits[1]->count; + /* Register the new edge from SWITCH_BB in loop exit lists. */ rescan_loop_exit (snew, true, false); @@ -7244,7 +7255,7 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, basic_block after, bb, *entry_pred, *exit_succ, abb; struct function *saved_cfun = cfun; int *entry_flag, *exit_flag; - unsigned *entry_prob, *exit_prob; + profile_probability *entry_prob, *exit_prob; unsigned i, num_entry_edges, num_exit_edges, num_nodes; edge e; edge_iterator ei; @@ -7282,7 +7293,7 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, num_entry_edges = EDGE_COUNT (entry_bb->preds); entry_pred = XNEWVEC (basic_block, num_entry_edges); entry_flag = XNEWVEC (int, num_entry_edges); - entry_prob = XNEWVEC (unsigned, num_entry_edges); + entry_prob = XNEWVEC (profile_probability, num_entry_edges); i = 0; for (ei = ei_start (entry_bb->preds); (e = ei_safe_edge (ei)) != NULL;) { @@ -7297,7 +7308,7 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, num_exit_edges = EDGE_COUNT (exit_bb->succs); exit_succ = XNEWVEC (basic_block, num_exit_edges); exit_flag = XNEWVEC (int, num_exit_edges); - exit_prob = XNEWVEC (unsigned, num_exit_edges); + exit_prob = XNEWVEC (profile_probability, num_exit_edges); i = 0; for (ei = ei_start (exit_bb->succs); (e = ei_safe_edge (ei)) != NULL;) { @@ -8212,7 +8223,9 @@ gimple_flow_call_edges_add (sbitmap blocks) if (e) blocks_split++; } - make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_FAKE); + e = make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_FAKE); + e->probability = profile_probability::guessed_never (); + e->count = profile_count::guessed_zero (); } gsi_prev (&gsi); } @@ -8221,7 +8234,7 @@ gimple_flow_call_edges_add (sbitmap blocks) } if (blocks_split) - verify_flow_info (); + checking_verify_flow_info (); return blocks_split; } @@ -8703,9 +8716,11 @@ make_pass_split_crit_edges (gcc::context *ctxt) /* Insert COND expression which is GIMPLE_COND after STMT in basic block BB with appropriate basic block split and creation of a new conditionally executed basic block. + Update profile so the new bb is visited with probability PROB. Return created basic block. */ basic_block -insert_cond_bb (basic_block bb, gimple *stmt, gimple *cond) +insert_cond_bb (basic_block bb, gimple *stmt, gimple *cond, + profile_probability prob) { edge fall = split_block (bb, stmt); gimple_stmt_iterator iter = gsi_last_bb (bb); @@ -8720,11 +8735,17 @@ insert_cond_bb (basic_block bb, gimple *stmt, gimple *cond) /* Create conditionally executed block. */ new_bb = create_empty_bb (bb); - make_edge (bb, new_bb, EDGE_TRUE_VALUE); + edge e = make_edge (bb, new_bb, EDGE_TRUE_VALUE); + e->probability = prob; + e->count = bb->count.apply_probability (prob); + new_bb->count = e->count; + new_bb->frequency = prob.apply (bb->frequency); make_single_succ_edge (new_bb, fall->dest, EDGE_FALLTHRU); /* Fix edge for split bb. */ fall->flags = EDGE_FALSE_VALUE; + fall->count -= e->count; + fall->probability -= e->probability; /* Update dominance info. */ if (dom_info_available_p (CDI_DOMINATORS)) |