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
This commit is contained in:
parent
9714133875
commit
15db5571d1
6 changed files with 89 additions and 26 deletions
|
@ -1,3 +1,12 @@
|
|||
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>
|
||||
|
||||
* 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);
|
|||
extern edge try_redirect_by_replacing_jump (edge, basic_block, bool);
|
||||
extern void break_superblocks (void);
|
||||
extern void check_bb_profile (basic_block, FILE *);
|
||||
extern void update_bb_profile_for_threading (basic_block, int, gcov_type, edge);
|
||||
|
||||
#include "cfghooks.h"
|
||||
|
||||
|
|
61
gcc/cfg.c
61
gcc/cfg.c
|
@ -888,3 +888,64 @@ brief_dump_cfg (FILE *file)
|
|||
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)
|
|||
{
|
||||
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)
|
||||
{
|
||||
edge e;
|
||||
int prob;
|
||||
|
||||
gcc_assert (n < nthreaded_edges);
|
||||
t = threaded_edges [n++];
|
||||
gcc_assert (t->src == first);
|
||||
if (first->frequency)
|
||||
prob = edge_frequency * REG_BR_PROB_BASE / first->frequency;
|
||||
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_bb_profile_for_threading (first, edge_frequency,
|
||||
edge_count, t);
|
||||
update_br_prob_note (first);
|
||||
}
|
||||
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
|
||||
threading we've removed edge as it is
|
||||
threaded to the fallthru edge. Avoid
|
||||
|
|
|
@ -697,6 +697,8 @@ thread_across_edge (struct dom_walk_data *walk_data, edge e)
|
|||
bypass the conditional at our original destination. */
|
||||
if (dest)
|
||||
{
|
||||
update_bb_profile_for_threading (e->dest, EDGE_FREQUENCY (e),
|
||||
e->count, taken_edge);
|
||||
e->aux = taken_edge;
|
||||
bb_ann (e->dest)->incoming_edge_threaded = true;
|
||||
}
|
||||
|
|
|
@ -172,17 +172,25 @@ static void
|
|||
create_block_for_threading (basic_block bb, struct redirection_data *rd)
|
||||
{
|
||||
tree phi;
|
||||
edge e;
|
||||
|
||||
/* We can use the generic block duplication code and simply remove
|
||||
the stuff we do not need. */
|
||||
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
|
||||
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
|
||||
specialized block copier. */
|
||||
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
|
||||
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
|
||||
|
|
Loading…
Add table
Reference in a new issue