tree-cfgcleanup.c (cfgcleanup_altered_bbs): New global variable.
authorZdenek Dvorak <dvorakz@suse.cz>
Thu, 26 Apr 2007 23:13:41 +0000 (01:13 +0200)
committerZdenek Dvorak <rakdver@gcc.gnu.org>
Thu, 26 Apr 2007 23:13:41 +0000 (23:13 +0000)
* tree-cfgcleanup.c (cfgcleanup_altered_bbs): New global variable.
(remove_fallthru_edge): Use remove_edge_and_dominated_blocks.
(cleanup_control_expr_graph): Do not invalidate dominance info.
Record altered blocks.
(cleanup_control_flow, cleanup_forwarder_blocks): Removed.
(cleanup_control_flow_bb, split_bbs_on_noreturn_calls,
cleanup_tree_cfg_bb): New functions.
(remove_forwarder_block): Do not maintain the worklist of blocks.
Record altered blocks.
(cleanup_tree_cfg_1): Iterate over cfgcleanup_altered_bbs,
not over whole cfg.
(cleanup_tree_cfg): Do not iterate cleanup_tree_cfg_1.  Only call
delete_unreachable_blocks if dominators are not available.
* tree-inline.c (optimize_inline_calls): Free dominance information
earlier.
* tree-flow.h (remove_edge_and_dominated_blocks,
cfgcleanup_altered_bbs): Altered.
* tree-cfg.c (replace_uses_by, tree_merge_blocks): Record altered
blocks.
(get_all_dominated_blocks, remove_edge_and_dominated_blocks): New
functions.
(tree_purge_dead_eh_edges): Use remove_edge_and_dominated_blocks,
do not invalidate dominators.

From-SVN: r124203

gcc/ChangeLog
gcc/tree-cfg.c
gcc/tree-cfgcleanup.c
gcc/tree-flow.h
gcc/tree-inline.c

index 726e783c49a414b7560d6fef0f466ee860f04e27..2b6d43c4c971883a30f3fb81e2a6c111751b21f7 100644 (file)
@@ -1,3 +1,29 @@
+2007-04-27  Zdenek Dvorak  <dvorakz@suse.cz>
+
+       * tree-cfgcleanup.c (cfgcleanup_altered_bbs): New global variable.
+       (remove_fallthru_edge): Use remove_edge_and_dominated_blocks.
+       (cleanup_control_expr_graph): Do not invalidate dominance info.
+       Record altered blocks.
+       (cleanup_control_flow, cleanup_forwarder_blocks): Removed.
+       (cleanup_control_flow_bb, split_bbs_on_noreturn_calls,
+       cleanup_tree_cfg_bb): New functions.
+       (remove_forwarder_block): Do not maintain the worklist of blocks.
+       Record altered blocks.
+       (cleanup_tree_cfg_1): Iterate over cfgcleanup_altered_bbs,
+       not over whole cfg.
+       (cleanup_tree_cfg): Do not iterate cleanup_tree_cfg_1.  Only call
+       delete_unreachable_blocks if dominators are not available.
+       * tree-inline.c (optimize_inline_calls): Free dominance information
+       earlier.
+       * tree-flow.h (remove_edge_and_dominated_blocks,
+       cfgcleanup_altered_bbs): Altered.
+       * tree-cfg.c (replace_uses_by, tree_merge_blocks): Record altered
+       blocks.
+       (get_all_dominated_blocks, remove_edge_and_dominated_blocks): New
+       functions.
+       (tree_purge_dead_eh_edges): Use remove_edge_and_dominated_blocks,
+       do not invalidate dominators.
+
 2007-04-26  Anatoly Sokolov <aesok@post.ru>
 
        * config/avr/avr.c (avr_mcu_types): Add support for ATmega8HVA and 
index a621d9d6b0588b6199ff15468ff5bd8d35e2a43b..878ba6fa808729ef953db3c1b2e1b52632ac30c4 100644 (file)
@@ -1199,6 +1199,8 @@ replace_uses_by (tree name, tree val)
          tree rhs;
 
          fold_stmt_inplace (stmt);
+         if (cfgcleanup_altered_bbs)
+           bitmap_set_bit (cfgcleanup_altered_bbs, bb_for_stmt (stmt)->index);
 
          /* FIXME.  This should go in pop_stmt_changes.  */
          rhs = get_rhs (stmt);
@@ -1312,6 +1314,9 @@ tree_merge_blocks (basic_block a, basic_block b)
   last = tsi_last (bb_stmt_list (a));
   tsi_link_after (&last, bb_stmt_list (b), TSI_NEW_STMT);
   set_bb_stmt_list (b, NULL_TREE);
+
+  if (cfgcleanup_altered_bbs)
+    bitmap_set_bit (cfgcleanup_altered_bbs, a->index);
 }
 
 
@@ -5429,6 +5434,144 @@ tree_purge_dead_abnormal_call_edges (basic_block bb)
   return changed;
 }
 
+/* Stores all basic blocks dominated by BB to DOM_BBS.  */
+
+static void
+get_all_dominated_blocks (basic_block bb, VEC (basic_block, heap) **dom_bbs)
+{
+  basic_block son;
+
+  VEC_safe_push (basic_block, heap, *dom_bbs, bb);
+  for (son = first_dom_son (CDI_DOMINATORS, bb);
+       son;
+       son = next_dom_son (CDI_DOMINATORS, son))
+    get_all_dominated_blocks (son, dom_bbs);
+}
+
+/* Removes edge E and all the blocks dominated by it, and updates dominance
+   information.  The IL in E->src needs to be updated separately.
+   If dominance info is not available, only the edge E is removed.*/
+
+void
+remove_edge_and_dominated_blocks (edge e)
+{
+  VEC (basic_block, heap) *bbs_to_remove = NULL;
+  VEC (basic_block, heap) *bbs_to_fix_dom = NULL;
+  bitmap df, df_idom;
+  edge f;
+  edge_iterator ei;
+  bool none_removed = false;
+  unsigned i;
+  basic_block bb, dbb;
+  bitmap_iterator bi;
+
+  if (!dom_computed[CDI_DOMINATORS])
+    {
+      remove_edge (e);
+      return;
+    }
+
+  /* No updating is needed for edges to exit.  */
+  if (e->dest == EXIT_BLOCK_PTR)
+    {
+      if (cfgcleanup_altered_bbs)
+       bitmap_set_bit (cfgcleanup_altered_bbs, e->src->index);
+      remove_edge (e);
+      return;
+    }
+
+  /* First, we find the basic blocks to remove.  If E->dest has a predecessor
+     that is not dominated by E->dest, then this set is empty.  Otherwise,
+     all the basic blocks dominated by E->dest are removed.
+
+     Also, to DF_IDOM we store the immediate dominators of the blocks in
+     the dominance frontier of E (i.e., of the successors of the
+     removed blocks, if there are any, and of E->dest otherwise).  */
+  FOR_EACH_EDGE (f, ei, e->dest->preds)
+    {
+      if (f == e)
+       continue;
+
+      if (!dominated_by_p (CDI_DOMINATORS, f->src, e->dest))
+       {
+         none_removed = true;
+         break;
+       }
+    }
+
+  df = BITMAP_ALLOC (NULL);
+  df_idom = BITMAP_ALLOC (NULL);
+
+  if (none_removed)
+    bitmap_set_bit (df_idom,
+                   get_immediate_dominator (CDI_DOMINATORS, e->dest)->index);
+  else
+    {
+      get_all_dominated_blocks (e->dest, &bbs_to_remove);
+      for (i = 0; VEC_iterate (basic_block, bbs_to_remove, i, bb); i++)
+       {
+         FOR_EACH_EDGE (f, ei, bb->succs)
+           {
+             if (f->dest != EXIT_BLOCK_PTR)
+               bitmap_set_bit (df, f->dest->index);
+           }
+       }
+      for (i = 0; VEC_iterate (basic_block, bbs_to_remove, i, bb); i++)
+       bitmap_clear_bit (df, bb->index);
+
+      EXECUTE_IF_SET_IN_BITMAP (df, 0, i, bi)
+       {
+         bb = BASIC_BLOCK (i);
+         bitmap_set_bit (df_idom,
+                         get_immediate_dominator (CDI_DOMINATORS, bb)->index);
+       }
+    }
+
+  if (cfgcleanup_altered_bbs)
+    {
+      /* Record the set of the altered basic blocks.  */
+      bitmap_set_bit (cfgcleanup_altered_bbs, e->src->index);
+      bitmap_ior_into (cfgcleanup_altered_bbs, df);
+    }
+
+  /* Remove E and the cancelled blocks.  */
+  if (none_removed)
+    remove_edge (e);
+  else
+    {
+      for (i = 0; VEC_iterate (basic_block, bbs_to_remove, i, bb); i++)
+       delete_basic_block (bb);
+    }
+
+  /* Update the dominance information.  The immediate dominator may change only
+     for blocks whose immediate dominator belongs to DF_IDOM:
+   
+     Suppose that idom(X) = Y before removal of E and idom(X) != Y after the
+     removal.  Let Z the arbitrary block such that idom(Z) = Y and
+     Z dominates X after the removal.  Before removal, there exists a path P
+     from Y to X that avoids Z.  Let F be the last edge on P that is
+     removed, and let W = F->dest.  Before removal, idom(W) = Y (since Y
+     dominates W, and because of P, Z does not dominate W), and W belongs to
+     the dominance frontier of E.  Therefore, Y belongs to DF_IDOM.  */ 
+  EXECUTE_IF_SET_IN_BITMAP (df_idom, 0, i, bi)
+    {
+      bb = BASIC_BLOCK (i);
+      for (dbb = first_dom_son (CDI_DOMINATORS, bb);
+          dbb;
+          dbb = next_dom_son (CDI_DOMINATORS, dbb))
+       VEC_safe_push (basic_block, heap, bbs_to_fix_dom, dbb);
+    }
+
+  iterate_fix_dominators (CDI_DOMINATORS,
+                         VEC_address (basic_block, bbs_to_fix_dom),
+                         VEC_length (basic_block, bbs_to_fix_dom));
+
+  BITMAP_FREE (df);
+  BITMAP_FREE (df_idom);
+  VEC_free (basic_block, heap, bbs_to_remove);
+  VEC_free (basic_block, heap, bbs_to_fix_dom);
+}
+
 /* Purge dead EH edges from basic block BB.  */
 
 bool
@@ -5446,33 +5589,13 @@ tree_purge_dead_eh_edges (basic_block bb)
     {
       if (e->flags & EDGE_EH)
        {
-         remove_edge (e);
+         remove_edge_and_dominated_blocks (e);
          changed = true;
        }
       else
        ei_next (&ei);
     }
 
-  /* Removal of dead EH edges might change dominators of not
-     just immediate successors.  E.g. when bb1 is changed so that
-     it no longer can throw and bb1->bb3 and bb1->bb4 are dead
-     eh edges purged by this function in:
-           0
-         / \
-        v   v
-        1-->2
-        / \  |
-       v   v |
-       3-->4 |
-        \    v
-        --->5
-            |
-            -
-     idom(bb5) must be recomputed.  For now just free the dominance
-     info.  */
-  if (changed)
-    free_dominance_info (CDI_DOMINATORS);
-
   return changed;
 }
 
index 39dcfe7c3abf1caffa65badd75cf32e46a4dde26..92ac2375026ccedb29c832cf64da826e152c11bf 100644 (file)
@@ -48,6 +48,15 @@ Boston, MA 02110-1301, USA.  */
 #include "tree-ssa-propagate.h"
 #include "tree-scalar-evolution.h"
 
+/* The set of blocks in that at least one of the following changes happened:
+   -- the statement at the end of the block was changed
+   -- the block was newly created
+   -- the set of the predecessors of the block changed
+   -- the set of the successors of the block changed
+   ??? Maybe we could track these changes separately, since they determine
+       what cleanups it makes sense to try on the block.  */
+bitmap cfgcleanup_altered_bbs;
+
 /* Remove any fallthru edge from EV.  Return true if an edge was removed.  */
 
 static bool
@@ -59,7 +68,7 @@ remove_fallthru_edge (VEC(edge,gc) *ev)
   FOR_EACH_EDGE (e, ei, ev)
     if ((e->flags & EDGE_FALLTHRU) != 0)
       {
-       remove_edge (e);
+       remove_edge_and_dominated_blocks (e);
        return true;
       }
   return false;
@@ -124,7 +133,7 @@ cleanup_control_expr_graph (basic_block bb, block_stmt_iterator bsi)
 
              taken_edge->probability += e->probability;
              taken_edge->count += e->count;
-             remove_edge (e);
+             remove_edge_and_dominated_blocks (e);
              retval = true;
            }
          else
@@ -138,106 +147,82 @@ cleanup_control_expr_graph (basic_block bb, block_stmt_iterator bsi)
   else
     taken_edge = single_succ_edge (bb);
 
+  bitmap_set_bit (cfgcleanup_altered_bbs, bb->index);
   bsi_remove (&bsi, true);
   taken_edge->flags = EDGE_FALLTHRU;
 
-  /* We removed some paths from the cfg.  */
-  free_dominance_info (CDI_DOMINATORS);
-
   return retval;
 }
 
-/* Try to remove superfluous control structures.  */
+/* Try to remove superfluous control structures in basic block BB.  Returns
+   true if anything changes.  */
 
 static bool
-cleanup_control_flow (void)
+cleanup_control_flow_bb (basic_block bb)
 {
-  basic_block bb;
   block_stmt_iterator bsi;
   bool retval = false;
   tree stmt;
 
-  /* Detect cases where a mid-block call is now known not to return.  */
-  if (cfun->gimple_df)
-    while (VEC_length (tree, MODIFIED_NORETURN_CALLS (cfun)))
-      {
-       stmt = VEC_pop (tree, MODIFIED_NORETURN_CALLS (cfun));
-       bb = bb_for_stmt (stmt);
-       if (bb != NULL && last_stmt (bb) != stmt && noreturn_call_p (stmt))
-         split_block (bb, stmt);
-      }
-
-  FOR_EACH_BB (bb)
+  /* If the last statement of the block could throw and now cannot,
+     we need to prune cfg.  */
+  retval |= tree_purge_dead_eh_edges (bb);
+
+  bsi = bsi_last (bb);
+  if (bsi_end_p (bsi))
+    return retval;
+
+  stmt = bsi_stmt (bsi);
+
+  if (TREE_CODE (stmt) == COND_EXPR
+      || TREE_CODE (stmt) == SWITCH_EXPR)
+    retval |= cleanup_control_expr_graph (bb, bsi);
+  /* If we had a computed goto which has a compile-time determinable
+     destination, then we can eliminate the goto.  */
+  else if (TREE_CODE (stmt) == GOTO_EXPR
+          && TREE_CODE (GOTO_DESTINATION (stmt)) == ADDR_EXPR
+          && (TREE_CODE (TREE_OPERAND (GOTO_DESTINATION (stmt), 0))
+              == LABEL_DECL))
     {
-      bsi = bsi_last (bb);
-
-      /* If the last statement of the block could throw and now cannot,
-        we need to prune cfg.  */
-      retval |= tree_purge_dead_eh_edges (bb);
-
-      if (bsi_end_p (bsi))
-       continue;
+      edge e;
+      tree label;
+      edge_iterator ei;
+      basic_block target_block;
 
-      stmt = bsi_stmt (bsi);
-
-      if (TREE_CODE (stmt) == COND_EXPR
-         || TREE_CODE (stmt) == SWITCH_EXPR)
-       retval |= cleanup_control_expr_graph (bb, bsi);
-      /* If we had a computed goto which has a compile-time determinable
-        destination, then we can eliminate the goto.  */
-      else if (TREE_CODE (stmt) == GOTO_EXPR
-              && TREE_CODE (GOTO_DESTINATION (stmt)) == ADDR_EXPR
-              && (TREE_CODE (TREE_OPERAND (GOTO_DESTINATION (stmt), 0))
-                  == LABEL_DECL))
+      /* First look at all the outgoing edges.  Delete any outgoing
+        edges which do not go to the right block.  For the one
+        edge which goes to the right block, fix up its flags.  */
+      label = TREE_OPERAND (GOTO_DESTINATION (stmt), 0);
+      target_block = label_to_block (label);
+      for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
        {
-         edge e;
-         tree label;
-         edge_iterator ei;
-         basic_block target_block;
-         bool removed_edge = false;
-
-         /* First look at all the outgoing edges.  Delete any outgoing
-            edges which do not go to the right block.  For the one
-            edge which goes to the right block, fix up its flags.  */
-         label = TREE_OPERAND (GOTO_DESTINATION (stmt), 0);
-         target_block = label_to_block (label);
-         for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
+         if (e->dest != target_block)
+           remove_edge_and_dominated_blocks (e);
+         else
            {
-             if (e->dest != target_block)
-               {
-                 removed_edge = true;
-                 remove_edge (e);
-               }
-             else
-               {
-                 /* Turn off the EDGE_ABNORMAL flag.  */
-                 e->flags &= ~EDGE_ABNORMAL;
-
-                 /* And set EDGE_FALLTHRU.  */
-                 e->flags |= EDGE_FALLTHRU;
-                 ei_next (&ei);
-               }
-           }
+             /* Turn off the EDGE_ABNORMAL flag.  */
+             e->flags &= ~EDGE_ABNORMAL;
 
-         /* If we removed one or more edges, then we will need to fix the
-            dominators.  It may be possible to incrementally update them.  */
-         if (removed_edge)
-           free_dominance_info (CDI_DOMINATORS);
-
-         /* Remove the GOTO_EXPR as it is not needed.  The CFG has all the
-            relevant information we need.  */
-         bsi_remove (&bsi, true);
-         retval = true;
+             /* And set EDGE_FALLTHRU.  */
+             e->flags |= EDGE_FALLTHRU;
+             ei_next (&ei);
+           }
        }
 
-      /* Check for indirect calls that have been turned into
-        noreturn calls.  */
-      else if (noreturn_call_p (stmt) && remove_fallthru_edge (bb->succs))
-       {
-         free_dominance_info (CDI_DOMINATORS);
-         retval = true;
-       }
+      bitmap_set_bit (cfgcleanup_altered_bbs, bb->index);
+      bitmap_set_bit (cfgcleanup_altered_bbs, target_block->index);
+
+      /* Remove the GOTO_EXPR as it is not needed.  The CFG has all the
+        relevant information we need.  */
+      bsi_remove (&bsi, true);
+      retval = true;
     }
+
+  /* Check for indirect calls that have been turned into
+     noreturn calls.  */
+  else if (noreturn_call_p (stmt) && remove_fallthru_edge (bb->succs))
+    retval = true;
+
   return retval;
 }
 
@@ -366,12 +351,10 @@ phi_alternatives_equal (basic_block dest, edge e1, edge e2)
   return true;
 }
 
-/* Removes forwarder block BB.  Returns false if this failed.  If a new
-   forwarder block is created due to redirection of edges, it is
-   stored to worklist.  */
+/* Removes forwarder block BB.  Returns false if this failed.  */
 
 static bool
-remove_forwarder_block (basic_block bb, basic_block **worklist)
+remove_forwarder_block (basic_block bb)
 {
   edge succ = single_succ_edge (bb), e, s;
   basic_block dest = succ->dest;
@@ -434,6 +417,8 @@ remove_forwarder_block (basic_block bb, basic_block **worklist)
   /* Redirect the edges.  */
   for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
     {
+      bitmap_set_bit (cfgcleanup_altered_bbs, e->src->index);
+
       if (e->flags & EDGE_ABNORMAL)
        {
          /* If there is an abnormal edge, redirect it anyway, and
@@ -450,15 +435,6 @@ remove_forwarder_block (basic_block bb, basic_block **worklist)
          for (phi = phi_nodes (dest); phi; phi = PHI_CHAIN (phi))
            add_phi_arg (phi, PHI_ARG_DEF (phi, succ->dest_idx), s);
        }
-      else
-       {
-         /* The source basic block might become a forwarder.  We know
-            that it was not a forwarder before, since it used to have
-            at least two outgoing edges, so we may just add it to
-            worklist.  */
-         if (tree_forwarder_block_p (s->src, false))
-           *(*worklist)++ = s->src;
-       }
     }
 
   if (seen_abnormal_edge)
@@ -476,6 +452,8 @@ remove_forwarder_block (basic_block bb, basic_block **worklist)
        }
     }
 
+  bitmap_set_bit (cfgcleanup_altered_bbs, dest->index);
+
   /* Update the dominators.  */
   if (dom_info_available_p (CDI_DOMINATORS))
     {
@@ -501,65 +479,120 @@ remove_forwarder_block (basic_block bb, basic_block **worklist)
   return true;
 }
 
-/* Removes forwarder blocks.  */
+/* Split basic blocks on calls in the middle of a basic block that are now
+   known not to return, and remove the unreachable code.  */
 
 static bool
-cleanup_forwarder_blocks (void)
+split_bbs_on_noreturn_calls (void)
 {
-  basic_block bb;
   bool changed = false;
-  basic_block *worklist = XNEWVEC (basic_block, n_basic_blocks);
-  basic_block *current = worklist;
-
-  FOR_EACH_BB (bb)
-    {
-      if (tree_forwarder_block_p (bb, false))
-       *current++ = bb;
-    }
+  tree stmt;
+  basic_block bb;
 
-  while (current != worklist)
-    {
-      bb = *--current;
-      changed |= remove_forwarder_block (bb, &current);
-    }
+  /* Detect cases where a mid-block call is now known not to return.  */
+  if (cfun->gimple_df)
+    while (VEC_length (tree, MODIFIED_NORETURN_CALLS (cfun)))
+      {
+       stmt = VEC_pop (tree, MODIFIED_NORETURN_CALLS (cfun));
+       bb = bb_for_stmt (stmt);
+       if (bb == NULL
+           || last_stmt (bb) == stmt
+           || !noreturn_call_p (stmt))
+         continue;
+
+       changed = true;
+       split_block (bb, stmt);
+       remove_fallthru_edge (bb->succs);
+      }
 
-  free (worklist);
   return changed;
 }
 
-/* Do one round of CFG cleanup.  */
+/* Tries to cleanup cfg in basic block BB.  Returns true if anything
+   changes.  */
 
 static bool
-cleanup_tree_cfg_1 (void)
+cleanup_tree_cfg_bb (basic_block bb)
 {
-  bool retval;
+  bool retval = false;
 
-  retval = cleanup_control_flow ();
-  retval |= delete_unreachable_blocks ();
+  retval = cleanup_control_flow_bb (bb);
 
   /* Forwarder blocks can carry line number information which is
      useful when debugging, so we only clean them up when
      optimizing.  */
 
-  if (optimize > 0)
-    {
-      /* cleanup_forwarder_blocks can redirect edges out of
-        SWITCH_EXPRs, which can get expensive.  So we want to enable
-        recording of edge to CASE_LABEL_EXPR mappings around the call
-        to cleanup_forwarder_blocks.  */
-      start_recording_case_labels ();
-      retval |= cleanup_forwarder_blocks ();
-      end_recording_case_labels ();
-    }
+  if (optimize > 0
+      && tree_forwarder_block_p (bb, false)
+      && remove_forwarder_block (bb))
+    return true;
 
   /* Merging the blocks may create new opportunities for folding
      conditional branches (due to the elimination of single-valued PHI
      nodes).  */
-  retval |= merge_seq_blocks ();
+  if (single_succ_p (bb)
+      && can_merge_blocks_p (bb, single_succ (bb)))
+    {
+      merge_blocks (bb, single_succ (bb));
+      return true;
+    }
 
   return retval;
 }
 
+/* Iterate the cfg cleanups, while anything changes.  */
+
+static bool
+cleanup_tree_cfg_1 (void)
+{
+  bool retval = false;
+  basic_block bb;
+  unsigned i, n;
+
+  retval |= split_bbs_on_noreturn_calls ();
+
+  /* Prepare the worklists of altered blocks.  */
+  cfgcleanup_altered_bbs = BITMAP_ALLOC (NULL);
+
+  /* During forwarder block cleanup, we may redirect edges out of
+     SWITCH_EXPRs, which can get expensive.  So we want to enable
+     recording of edge to CASE_LABEL_EXPR.  */
+  start_recording_case_labels ();
+
+  /* Start by iterating over all basic blocks.  We cannot use FOR_EACH_BB,
+     since the basic blocks may get removed.  */
+  n = last_basic_block;
+  for (i = NUM_FIXED_BLOCKS; i < n; i++)
+    {
+      bb = BASIC_BLOCK (i);
+      if (bb)
+       retval |= cleanup_tree_cfg_bb (bb);
+    }
+
+  /* Now process the altered blocks, as long as any are available.  */
+  while (!bitmap_empty_p (cfgcleanup_altered_bbs))
+    {
+      i = bitmap_first_set_bit (cfgcleanup_altered_bbs);
+      bitmap_clear_bit (cfgcleanup_altered_bbs, i);
+      if (i < NUM_FIXED_BLOCKS)
+       continue;
+
+      bb = BASIC_BLOCK (i);
+      if (!bb)
+       continue;
+
+      retval |= cleanup_tree_cfg_bb (bb);
+
+      /* Rerun split_bbs_on_noreturn_calls, in case we have altered any noreturn
+        calls.  */
+      retval |= split_bbs_on_noreturn_calls ();
+    }
+  
+  end_recording_case_labels ();
+  BITMAP_FREE (cfgcleanup_altered_bbs);
+  return retval;
+}
+
 
 /* Remove unreachable blocks and other miscellaneous clean up work.
    Return true if the flowgraph was modified, false otherwise.  */
@@ -567,20 +600,26 @@ cleanup_tree_cfg_1 (void)
 bool
 cleanup_tree_cfg (void)
 {
-  bool retval, changed;
+  bool changed;
 
   timevar_push (TV_TREE_CLEANUP_CFG);
 
   /* Iterate until there are no more cleanups left to do.  If any
-     iteration changed the flowgraph, set CHANGED to true.  */
-  changed = false;
-  do
+     iteration changed the flowgraph, set CHANGED to true.
+
+     If dominance information is available, there cannot be any unreachable
+     blocks.  */
+  if (!dom_computed[CDI_DOMINATORS])
     {
-      retval = cleanup_tree_cfg_1 ();
-      changed |= retval;
+      changed = delete_unreachable_blocks ();
+      calculate_dominance_info (CDI_DOMINATORS);
     }
-  while (retval);
+  else
+    changed = false;
 
+  changed |= cleanup_tree_cfg_1 ();
+
+  gcc_assert (dom_computed[CDI_DOMINATORS]);
   compact_blocks ();
 
 #ifdef ENABLE_CHECKING
@@ -602,7 +641,6 @@ cleanup_tree_cfg_loop (void)
   if (changed && current_loops != NULL)
     {
       bitmap changed_bbs = BITMAP_ALLOC (NULL);
-      calculate_dominance_info (CDI_DOMINATORS);
       fix_loop_structure (changed_bbs);
 
       /* This usually does nothing.  But sometimes parts of cfg that originally
index 4d9b36e4ab885c2fb3a0d64bdcd2d02212c0ee4f..b7f6585b9071384269622b4bbdd9d31140f7dfc9 100644 (file)
@@ -778,8 +778,10 @@ extern void start_recording_case_labels (void);
 extern void end_recording_case_labels (void);
 extern basic_block move_sese_region_to_fn (struct function *, basic_block,
                                           basic_block);
+void remove_edge_and_dominated_blocks (edge);
 
 /* In tree-cfgcleanup.c  */
+extern bitmap cfgcleanup_altered_bbs;
 extern bool cleanup_tree_cfg (void);
 extern bool cleanup_tree_cfg_loop (void);
 
index 77d3864605438b4c4d8985f9ac17c72453f786f5..ba8a71eeb87a617df9ba394e70999a7e4a7e146f 100644 (file)
@@ -2804,6 +2804,10 @@ optimize_inline_calls (tree fn)
 
   push_gimplify_context ();
 
+  /* We make no attempts to keep dominance info up-to-date.  */
+  free_dominance_info (CDI_DOMINATORS);
+  free_dominance_info (CDI_POST_DOMINATORS);
+
   /* Reach the trees by walking over the CFG, and note the
      enclosing basic-blocks in the call edges.  */
   /* We walk the blocks going forward, because inlined function bodies
@@ -2840,9 +2844,6 @@ optimize_inline_calls (tree fn)
   fold_cond_expr_cond ();
   if (current_function_has_nonlocal_label)
     make_nonlocal_label_edges ();
-  /* We make no attempts to keep dominance info up-to-date.  */
-  free_dominance_info (CDI_DOMINATORS);
-  free_dominance_info (CDI_POST_DOMINATORS);
   /* It would be nice to check SSA/CFG/statement consistency here, but it is
      not possible yet - the IPA passes might make various functions to not
      throw and they don't care to proactively update local EH info.  This is