aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2004-09-19 18:04:03 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2004-09-19 16:04:03 +0000
commit15db5571d1567a4d05812f85853b9b95766b8f2e (patch)
tree2864608d6a5ce3c527756be3a276cd609e29f91f /gcc
parent9714133875a19fcb1258b79d8c035d7a8d240d61 (diff)
downloadgcc-15db5571d1567a4d05812f85853b9b95766b8f2e.zip
gcc-15db5571d1567a4d05812f85853b9b95766b8f2e.tar.gz
gcc-15db5571d1567a4d05812f85853b9b95766b8f2e.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/basic-block.h1
-rw-r--r--gcc/cfg.c61
-rw-r--r--gcc/cfgcleanup.c34
-rw-r--r--gcc/tree-ssa-dom.c2
-rw-r--r--gcc/tree-ssa-threadupdate.c8
6 files changed, 89 insertions, 26 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4863acc..6bc408a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index 037f0ac..21fd7bb 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 3c2ef48..b5d28c3 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 08714f6..f9d0607 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 b99f189..f285011 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 ce6dcad..112509f 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