basic-block.h (update_bb_profile_after_threading): Declare.
authorJan Hubicka <jh@suse.cz>
Sun, 19 Sep 2004 16:04:03 +0000 (18:04 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sun, 19 Sep 2004 16:04:03 +0000 (16:04 +0000)
* 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
gcc/basic-block.h
gcc/cfg.c
gcc/cfgcleanup.c
gcc/tree-ssa-dom.c
gcc/tree-ssa-threadupdate.c

index 4863acc6929e32657ebf6e2e25333a35a9c8e432..6bc408a20c71116aa1a327355d2bdde59d186a70 100644 (file)
@@ -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
index 037f0ac4d47abe942a247978a17895a0a6f4d8aa..21fd7bb3babf98cf1aa1d8b83ddde24a197c68d3 100644 (file)
@@ -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"
 
index 3c2ef48d884ba2e5a0caf6ddfb67a5f263ef90ca..b5d28c3bed6421da7d01da406ae50f0b99b9a594 100644 (file)
--- 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;
+}
index 08714f6d652063df6284a89f4154cab7e76b144c..f9d06075caad6531eb29cc157153241f8b6acd9c 100644 (file)
@@ -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
index b99f1891fe54aa04a52068ae7a19cb4dedb9b13a..f285011ad49ac19bdcce1cd39fe99098ddc8b8bf 100644 (file)
@@ -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;
            }
index ce6dcad49481fc7c00657f0a9cf06606d53f36df..112509f46012575973ea32f49e241ee6494b2bda 100644 (file)
@@ -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