From 15db5571d1567a4d05812f85853b9b95766b8f2e Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Sun, 19 Sep 2004 18:04:03 +0200 Subject: [PATCH] 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 --- gcc/ChangeLog | 9 ++++++ gcc/basic-block.h | 1 + gcc/cfg.c | 61 +++++++++++++++++++++++++++++++++++++ gcc/cfgcleanup.c | 34 +++++---------------- gcc/tree-ssa-dom.c | 2 ++ gcc/tree-ssa-threadupdate.c | 8 +++++ 6 files changed, 89 insertions(+), 26 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4863acc6929..6bc408a20c7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2004-09-19 Jan Hubicka + + * 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 * tree-ssa-pre.c (insert_into_set): Don't put diff --git a/gcc/basic-block.h b/gcc/basic-block.h index 037f0ac4d47..21fd7bb3bab 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -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" diff --git a/gcc/cfg.c b/gcc/cfg.c index 3c2ef48d884..b5d28c3bed6 100644 --- a/gcc/cfg.c +++ b/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; +} diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index 08714f6d652..f9d06075caa 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -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 diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index b99f1891fe5..f285011ad49 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -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; } diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c index ce6dcad4948..112509f4601 100644 --- a/gcc/tree-ssa-threadupdate.c +++ b/gcc/tree-ssa-threadupdate.c @@ -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 -- 2.30.2