Commit 15db5571 by Jan Hubicka Committed by Jan Hubicka

basic-block.h (update_bb_profile_after_threading): Declare.

	* basic-block.h (update_bb_profile_after_threading): Declare.
	* cfg.c (update_bb_profile_after_threading): Break out from ...
	* cfgcleanup.c (try_forward_edges): ... here; use it.
	* tree-ssa-dom.c (thread_across_edge): Use it.
	* tree-ssa-threadupdate.c (create_block_for_threading): Zero out
	profile of the new BB.

From-SVN: r87730
parent 97141338
2004-09-19 Jan Hubicka <jh@suse.cz>
* basic-block.h (update_bb_profile_after_threading): Declare.
* cfg.c (update_bb_profile_after_threading): Break out from ...
* cfgcleanup.c (try_forward_edges): ... here; use it.
* tree-ssa-dom.c (thread_across_edge): Use it.
* tree-ssa-threadupdate.c (create_block_for_threading): Zero out
profile of the new BB.
2004-09-19 Daniel Berlin <dberlin@dberlin.org> 2004-09-19 Daniel Berlin <dberlin@dberlin.org>
* tree-ssa-pre.c (insert_into_set): Don't put * tree-ssa-pre.c (insert_into_set): Don't put
......
...@@ -746,6 +746,7 @@ extern basic_block next_dom_son (enum cdi_direction, basic_block); ...@@ -746,6 +746,7 @@ extern basic_block next_dom_son (enum cdi_direction, basic_block);
extern edge try_redirect_by_replacing_jump (edge, basic_block, bool); extern edge try_redirect_by_replacing_jump (edge, basic_block, bool);
extern void break_superblocks (void); extern void break_superblocks (void);
extern void check_bb_profile (basic_block, FILE *); extern void check_bb_profile (basic_block, FILE *);
extern void update_bb_profile_for_threading (basic_block, int, gcov_type, edge);
#include "cfghooks.h" #include "cfghooks.h"
......
...@@ -888,3 +888,64 @@ brief_dump_cfg (FILE *file) ...@@ -888,3 +888,64 @@ brief_dump_cfg (FILE *file)
dump_cfg_bb_info (file, bb); dump_cfg_bb_info (file, bb);
} }
} }
/* An edge originally destinating BB of FREQUENCY and COUNT has been proved to
leave the block by TAKEN_EDGE. Update profile of BB such that edge E can be
redirected to destiantion of TAKEN_EDGE.
This function may leave the profile inconsistent in the case TAKEN_EDGE
frequency or count is believed to be lower than FREQUENCY or COUNT
respectivly. */
void
update_bb_profile_for_threading (basic_block bb, int edge_frequency,
gcov_type count, edge taken_edge)
{
edge c;
int prob;
bb->count -= count;
if (bb->count < 0)
bb->count = 0;
/* Compute the probability of TAKEN_EDGE being reached via threaded edge.
Watch for overflows. */
if (bb->frequency)
prob = edge_frequency * REG_BR_PROB_BASE / bb->frequency;
else
prob = 0;
if (prob > taken_edge->probability)
{
if (dump_file)
fprintf (dump_file, "Jump threading proved probability of edge "
"%i->%i too small (it is %i, should be %i).\n",
taken_edge->src->index, taken_edge->dest->index,
taken_edge->probability, prob);
prob = taken_edge->probability;
}
/* Now rescale the probabilities. */
taken_edge->probability -= prob;
prob = REG_BR_PROB_BASE - prob;
bb->frequency -= edge_frequency;
if (bb->frequency < 0)
bb->frequency = 0;
if (prob <= 0)
{
if (dump_file)
fprintf (dump_file, "Edge frequencies of bb %i has been reset, "
"frequency of block should end up being 0, it is %i\n",
bb->index, bb->frequency);
bb->succ->probability = REG_BR_PROB_BASE;
for (c = bb->succ->succ_next; c; c = c->succ_next)
c->probability = 0;
}
else
for (c = bb->succ; c; c = c->succ_next)
c->probability = ((c->probability * REG_BR_PROB_BASE) / (double) prob);
if (bb != taken_edge->src)
abort ();
taken_edge->count -= count;
if (taken_edge->count < 0)
taken_edge->count = 0;
}
...@@ -614,41 +614,23 @@ try_forward_edges (int mode, basic_block b) ...@@ -614,41 +614,23 @@ try_forward_edges (int mode, basic_block b)
{ {
edge t; edge t;
first->count -= edge_count;
if (first->count < 0)
first->count = 0;
first->frequency -= edge_frequency;
if (first->frequency < 0)
first->frequency = 0;
if (first->succ->succ_next) if (first->succ->succ_next)
{ {
edge e;
int prob;
gcc_assert (n < nthreaded_edges); gcc_assert (n < nthreaded_edges);
t = threaded_edges [n++]; t = threaded_edges [n++];
gcc_assert (t->src == first); gcc_assert (t->src == first);
if (first->frequency) update_bb_profile_for_threading (first, edge_frequency,
prob = edge_frequency * REG_BR_PROB_BASE / first->frequency; edge_count, t);
else
prob = 0;
if (prob > t->probability)
prob = t->probability;
t->probability -= prob;
prob = REG_BR_PROB_BASE - prob;
if (prob <= 0)
{
first->succ->probability = REG_BR_PROB_BASE;
first->succ->succ_next->probability = 0;
}
else
for (e = first->succ; e; e = e->succ_next)
e->probability = ((e->probability * REG_BR_PROB_BASE)
/ (double) prob);
update_br_prob_note (first); update_br_prob_note (first);
} }
else else
{ {
first->count -= edge_count;
if (first->count < 0)
first->count = 0;
first->frequency -= edge_frequency;
if (first->frequency < 0)
first->frequency = 0;
/* It is possible that as the result of /* It is possible that as the result of
threading we've removed edge as it is threading we've removed edge as it is
threaded to the fallthru edge. Avoid threaded to the fallthru edge. Avoid
......
...@@ -697,6 +697,8 @@ thread_across_edge (struct dom_walk_data *walk_data, edge e) ...@@ -697,6 +697,8 @@ thread_across_edge (struct dom_walk_data *walk_data, edge e)
bypass the conditional at our original destination. */ bypass the conditional at our original destination. */
if (dest) if (dest)
{ {
update_bb_profile_for_threading (e->dest, EDGE_FREQUENCY (e),
e->count, taken_edge);
e->aux = taken_edge; e->aux = taken_edge;
bb_ann (e->dest)->incoming_edge_threaded = true; bb_ann (e->dest)->incoming_edge_threaded = true;
} }
......
...@@ -172,17 +172,25 @@ static void ...@@ -172,17 +172,25 @@ static void
create_block_for_threading (basic_block bb, struct redirection_data *rd) create_block_for_threading (basic_block bb, struct redirection_data *rd)
{ {
tree phi; tree phi;
edge e;
/* We can use the generic block duplication code and simply remove /* We can use the generic block duplication code and simply remove
the stuff we do not need. */ the stuff we do not need. */
rd->dup_block = duplicate_block (bb, NULL); rd->dup_block = duplicate_block (bb, NULL);
/* Zero out the profile, since the block is unreachable for now. */
rd->dup_block->frequency = 0;
rd->dup_block->count = 0;
/* The call to duplicate_block will copy everything, including the /* The call to duplicate_block will copy everything, including the
useless COND_EXPR or SWITCH_EXPR at the end of the block. We just remove useless COND_EXPR or SWITCH_EXPR at the end of the block. We just remove
the useless COND_EXPR or SWITCH_EXPR here rather than having a the useless COND_EXPR or SWITCH_EXPR here rather than having a
specialized block copier. */ specialized block copier. */
remove_last_stmt_and_useless_edges (rd->dup_block, rd->outgoing_edge->dest); remove_last_stmt_and_useless_edges (rd->dup_block, rd->outgoing_edge->dest);
for (e = rd->dup_block->succ; e; e = e->succ_next)
e->count = 0;
/* If there are any PHI nodes at the destination of the outgoing edge /* If there are any PHI nodes at the destination of the outgoing edge
from the duplicate block, then we will need to add a new argument from the duplicate block, then we will need to add a new argument
to them. The argument should have the same value as the argument to them. The argument should have the same value as the argument
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment