summaryrefslogtreecommitdiff
path: root/gcc/tree-cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r--gcc/tree-cfg.c135
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))