aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-threadupdate.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-threadupdate.c')
-rw-r--r--gcc/tree-ssa-threadupdate.c105
1 files changed, 62 insertions, 43 deletions
diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c
index 2da93a8..f85fed3 100644
--- a/gcc/tree-ssa-threadupdate.c
+++ b/gcc/tree-ssa-threadupdate.c
@@ -301,7 +301,11 @@ remove_ctrl_stmt_and_useless_edges (basic_block bb, basic_block dest_bb)
remove_edge (e);
}
else
- ei_next (&ei);
+ {
+ e->probability = REG_BR_PROB_BASE;
+ e->count = bb->count;
+ ei_next (&ei);
+ }
}
/* If the remaining edge is a loop exit, there must have
@@ -2212,8 +2216,8 @@ duplicate_thread_path (edge entry, edge exit,
struct loop *loop = entry->dest->loop_father;
edge exit_copy;
edge redirected;
- int total_freq = 0, entry_freq = 0;
- gcov_type total_count = 0, entry_count = 0;
+ int curr_freq;
+ gcov_type curr_count;
if (!can_copy_bbs_p (region, n_region))
return false;
@@ -2240,27 +2244,6 @@ duplicate_thread_path (edge entry, edge exit,
free_region_copy = true;
}
- if (entry->dest->count)
- {
- total_count = entry->dest->count;
- entry_count = entry->count;
- /* Fix up corner cases, to avoid division by zero or creation of negative
- frequencies. */
- if (entry_count > total_count)
- entry_count = total_count;
- }
- else
- {
- total_freq = entry->dest->frequency;
- entry_freq = EDGE_FREQUENCY (entry);
- /* Fix up corner cases, to avoid division by zero or creation of negative
- frequencies. */
- if (total_freq == 0)
- total_freq = 1;
- else if (entry_freq > total_freq)
- entry_freq = total_freq;
- }
-
copy_bbs (region, n_region, region_copy, &exit, 1, &exit_copy, loop,
split_edge_bb_loc (entry), false);
@@ -2270,17 +2253,61 @@ duplicate_thread_path (edge entry, edge exit,
invalidating the property that is propagated by executing all the blocks of
the jump-thread path in order. */
+ curr_count = entry->count;
+ curr_freq = EDGE_FREQUENCY (entry);
+
for (i = 0; i < n_region; i++)
{
edge e;
edge_iterator ei;
basic_block bb = region_copy[i];
+ /* Watch inconsistent profile. */
+ if (curr_count > region[i]->count)
+ curr_count = region[i]->count;
+ if (curr_freq > region[i]->frequency)
+ curr_freq = region[i]->frequency;
+ /* Scale current BB. */
+ if (region[i]->count)
+ {
+ /* In the middle of the path we only scale the frequencies.
+ In last BB we need to update probabilities of outgoing edges
+ because we know which one is taken at the threaded path. */
+ if (i + 1 != n_region)
+ scale_bbs_frequencies_gcov_type (region + i, 1,
+ region[i]->count - curr_count,
+ region[i]->count);
+ else
+ update_bb_profile_for_threading (region[i],
+ curr_freq, curr_count,
+ exit);
+ scale_bbs_frequencies_gcov_type (region_copy + i, 1, curr_count,
+ region_copy[i]->count);
+ }
+ else if (region[i]->frequency)
+ {
+ if (i + 1 != n_region)
+ scale_bbs_frequencies_int (region + i, 1,
+ region[i]->frequency - curr_freq,
+ region[i]->frequency);
+ else
+ update_bb_profile_for_threading (region[i],
+ curr_freq, curr_count,
+ exit);
+ scale_bbs_frequencies_int (region_copy + i, 1, curr_freq,
+ region_copy[i]->frequency);
+ }
+
if (single_succ_p (bb))
{
/* Make sure the successor is the next node in the path. */
gcc_assert (i + 1 == n_region
|| region_copy[i + 1] == single_succ_edge (bb)->dest);
+ if (i + 1 != n_region)
+ {
+ curr_freq = EDGE_FREQUENCY (single_succ_edge (bb));
+ curr_count = single_succ_edge (bb)->count;
+ }
continue;
}
@@ -2307,22 +2334,13 @@ duplicate_thread_path (edge entry, edge exit,
if (orig)
redirect_edge_and_branch_force (e, orig);
}
+ else
+ {
+ curr_freq = EDGE_FREQUENCY (e);
+ curr_count = e->count;
+ }
}
- if (total_count)
- {
- scale_bbs_frequencies_gcov_type (region, n_region,
- total_count - entry_count,
- total_count);
- scale_bbs_frequencies_gcov_type (region_copy, n_region, entry_count,
- total_count);
- }
- else
- {
- scale_bbs_frequencies_int (region, n_region, total_freq - entry_freq,
- total_freq);
- scale_bbs_frequencies_int (region_copy, n_region, entry_freq, total_freq);
- }
if (flag_checking)
verify_jump_thread (region_copy, n_region);
@@ -2337,11 +2355,12 @@ duplicate_thread_path (edge entry, edge exit,
edge e = make_edge (region_copy[n_region - 1], exit->dest, EDGE_FALLTHRU);
- if (e) {
- rescan_loop_exit (e, true, false);
- e->probability = REG_BR_PROB_BASE;
- e->count = region_copy[n_region - 1]->count;
- }
+ if (e)
+ {
+ rescan_loop_exit (e, true, false);
+ e->probability = REG_BR_PROB_BASE;
+ e->count = region_copy[n_region - 1]->count;
+ }
/* Redirect the entry and add the phi node arguments. */
if (entry->dest == loop->header)