OSDN Git Service

2001-11-11 H.J. Lu <hjl@gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / bb-reorder.c
index a6534d8..72cf90c 100644 (file)
@@ -1,22 +1,22 @@
 /* Basic block reordering routines for the GNU compiler.
    Copyright (C) 2000 Free Software Foundation, Inc.
 
-   This file is part of GNU CC.
+   This file is part of GCC.
 
-   GNU CC is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2, or (at your option)
    any later version.
 
-   GNU CC is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with GNU CC; see the file COPYING.  If not, write to
-   the Free Software Foundation, 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with GCC; see the file COPYING.  If not, write to the Free
+   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
 
 /* References:
 
 #include "system.h"
 #include "tree.h"
 #include "rtl.h"
-#include "tm_p.h"
 #include "hard-reg-set.h"
 #include "basic-block.h"
-#include "insn-config.h"
-#include "regs.h"
 #include "flags.h"
 #include "output.h"
-#include "function.h"
-#include "toplev.h"
-#include "recog.h"
-#include "expr.h"
-#include "obstack.h"
-
+#include "cfglayout.h"
 
 #ifndef HAVE_epilogue
 #define HAVE_epilogue 0
 #endif
 
-
-/* The contents of the current function definition are allocated
-   in this obstack, and all are freed at the end of the function.
-   For top-level functions, this is temporary_obstack.
-   Separate obstacks are made for nested functions.  */
-
-extern struct obstack flow_obstack;
-
-
-/* Structure to hold information about lexical scopes.  */
-typedef struct scope_def
-{
-  int level;
-
-  /* The NOTE_INSN_BLOCK_BEG that started this scope.  */
-  rtx note_beg;
-
-  /* The NOTE_INSN_BLOCK_END that ended this scope.  */
-  rtx note_end;
-
-  /* The bb containing note_beg (if any).  */
-  basic_block bb_beg;
-
-  /* The bb containing note_end (if any).  */
-  basic_block bb_end;
-
-  /* List of basic blocks contained within this scope.  */
-  basic_block *bbs;
-
-  /* Number of blocks contained within this scope.  */
-  int num_bbs;
-
-  /* The outer scope or NULL if outermost scope.  */
-  struct scope_def *outer;
-
-  /* The first inner scope or NULL if innermost scope.  */
-  struct scope_def *inner;
-
-  /* The last inner scope or NULL if innermost scope.  */
-  struct scope_def *inner_last;
-
-  /* Link to the next (sibling) scope.  */
-  struct scope_def *next;
-} *scope;
-
-
-/* Structure to hold information about the scope forest.  */
-typedef struct
-{
-  /* Number of trees in forest.  */
-  int num_trees;
-
-  /* List of tree roots.  */
-  scope *trees;
-} scope_forest_info;
-
-/* Structure to hold information about the blocks during reordering.  */
-typedef struct reorder_block_def
-{
-  rtx eff_head;
-  rtx eff_end;
-  scope scope;
-  basic_block next;
-  int index;
-  int visited;
-} *reorder_block_def;
-
-#define RBI(BB)        ((reorder_block_def) (BB)->aux)
-
-
 /* Local function prototypes.  */
-static rtx skip_insns_after_block      PARAMS ((basic_block));
-static void record_effective_endpoints PARAMS ((void));
 static void make_reorder_chain         PARAMS ((void));
 static basic_block make_reorder_chain_1        PARAMS ((basic_block, basic_block));
-static rtx label_for_bb                        PARAMS ((basic_block));
-static rtx emit_jump_to_block_after    PARAMS ((basic_block, rtx));
-static void fixup_reorder_chain                PARAMS ((void));
-static void relate_bbs_with_scopes     PARAMS ((scope));
-static scope make_new_scope            PARAMS ((int, rtx));
-static void build_scope_forest         PARAMS ((scope_forest_info *));
-static void remove_scope_notes         PARAMS ((void));
-static void insert_intra_1             PARAMS ((scope, rtx *));
-static void insert_intra_bb_scope_notes PARAMS ((basic_block));
-static void insert_inter_bb_scope_notes PARAMS ((basic_block, basic_block));
-static void rebuild_scope_notes                PARAMS ((scope_forest_info *));
-static void free_scope_forest_1                PARAMS ((scope));
-static void free_scope_forest          PARAMS ((scope_forest_info *));
-void dump_scope_forest                 PARAMS ((scope_forest_info *));
-static void dump_scope_forest_1                PARAMS ((scope, int));
-static rtx get_next_bb_note            PARAMS ((rtx));
-static rtx get_prev_bb_note            PARAMS ((rtx));
-
-void verify_insn_chain                 PARAMS ((void));
 \f
-/* Skip over inter-block insns occurring after BB which are typically
-   associated with BB (e.g., barriers). If there are any such insns,
-   we return the last one. Otherwise, we return the end of BB.  */
-
-static rtx
-skip_insns_after_block (bb)
-     basic_block bb;
-{
-  rtx insn, last_insn, next_head;
-
-  next_head = NULL_RTX;
-  if (bb->index + 1 != n_basic_blocks)
-    next_head = BASIC_BLOCK (bb->index + 1)->head;
-
-  for (last_insn = bb->end; (insn = NEXT_INSN (last_insn)); last_insn = insn)
-    {
-      if (insn == next_head)
-       break;
-
-      switch (GET_CODE (insn))
-       {
-       case BARRIER:
-         continue;
-
-       case NOTE:
-         switch (NOTE_LINE_NUMBER (insn))
-           {
-           case NOTE_INSN_LOOP_END:
-           case NOTE_INSN_BLOCK_END:
-           case NOTE_INSN_DELETED:
-           case NOTE_INSN_DELETED_LABEL:
-             continue;
-
-           default:
-             break;
-           }
-         break;
-
-       case CODE_LABEL:
-         if (NEXT_INSN (insn)
-             && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
-             && (GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC
-                 || GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_DIFF_VEC))
-           {
-             insn = NEXT_INSN (insn);
-             continue;
-           }
-          break;
-
-       default:
-         break;
-       }
-
-      break;
-    }
-
-  return last_insn;
-}
-
-
-/* Locate the effective beginning and end of the insn chain for each
-   block, as defined by skip_insns_after_block above.  */
-
-static void
-record_effective_endpoints ()
-{
-  rtx next_insn = get_insns ();
-  int i;
-  
-  for (i = 0; i < n_basic_blocks; ++i)
-    {
-      basic_block bb = BASIC_BLOCK (i);
-      rtx end;
-
-      RBI (bb)->eff_head = next_insn;
-      end = skip_insns_after_block (bb);
-      RBI (bb)->eff_end = end;
-      next_insn = NEXT_INSN (end);
-    }
-}
-
-
 /* Compute an ordering for a subgraph beginning with block BB.  Record the
    ordering in RBI()->index and chained through RBI()->next.  */
 
@@ -288,6 +107,7 @@ make_reorder_chain ()
   basic_block last_block = NULL;
   basic_block prev = NULL;
   int nbb_m1 = n_basic_blocks - 1;
+  basic_block next;
 
   /* If we've not got epilogue in RTL, we must fallthru to the exit.
      Force the last block to be at the end.  */
@@ -304,7 +124,8 @@ make_reorder_chain ()
   do
     {
       int i;
-      basic_block next = NULL;
+
+      next = NULL;
 
       /* Find the next unplaced block.  */
       /* ??? Get rid of this loop, and track which blocks are not yet
@@ -313,27 +134,21 @@ make_reorder_chain ()
         remove from the list as we place.  The head of that list is
         what we're looking for here.  */
 
-      for (i = 0; i <= nbb_m1; ++i)
+      for (i = 0; i <= nbb_m1 && !next; ++i)
        {
          basic_block bb = BASIC_BLOCK (i);
          if (! RBI (bb)->visited)
-           {
-             next = bb;
-             break;
-           }
+           next = bb;
        }
-      if (! next)
-       abort ();
-
-      prev = make_reorder_chain_1 (next, prev);
+      if (next)
+        prev = make_reorder_chain_1 (next, prev);
     }
-  while (RBI (prev)->index < nbb_m1);
+  while (next);
 
   /* Terminate the chain.  */
   if (! HAVE_epilogue)
     {
       RBI (prev)->next = last_block;
-      RBI (last_block)->index = RBI (prev)->index + 1;
       prev = last_block;
     }
   RBI (prev)->next = NULL;
@@ -362,19 +177,18 @@ make_reorder_chain_1 (bb, prev)
   /* Mark this block visited.  */
   if (prev)
     {
-      int new_index;
-
  restart:
       RBI (prev)->next = bb;
-      new_index = RBI (prev)->index + 1;
-      RBI (bb)->index = new_index;
 
       if (rtl_dump_file && prev->index + 1 != bb->index)
-       fprintf (rtl_dump_file, "Reordering block %d (%d) after %d (%d)\n",
-                bb->index, RBI (bb)->index, prev->index, RBI (prev)->index);
+       fprintf (rtl_dump_file, "Reordering block %d after %d\n",
+                bb->index, prev->index);
     }
   else
-    RBI (bb)->index = 0;
+    {
+      if (bb->index != 0)
+       abort ();
+    }
   RBI (bb)->visited = 1;
   prev = bb;
 
@@ -461,924 +275,20 @@ make_reorder_chain_1 (bb, prev)
   return prev;
 }
 
-
-/* Locate or create a label for a given basic block.  */
-
-static rtx
-label_for_bb (bb)
-     basic_block bb;
-{
-  rtx label = bb->head;
-
-  if (GET_CODE (label) != CODE_LABEL)
-    {
-      if (rtl_dump_file)
-       fprintf (rtl_dump_file, "Emitting label for block %d (%d)\n",
-                bb->index, RBI (bb)->index);
-
-      label = emit_label_before (gen_label_rtx (), label);
-      if (bb->head == RBI (bb)->eff_head)
-       RBI (bb)->eff_head = label;
-      bb->head = label;
-    }
-
-  return label;
-}
-
-
-/* Emit a jump to BB after insn AFTER.  */
-
-static rtx
-emit_jump_to_block_after (bb, after)
-     basic_block bb;
-     rtx after;
-{
-  rtx jump;
-
-  if (bb != EXIT_BLOCK_PTR)
-    {
-      rtx label = label_for_bb (bb);
-      jump = emit_jump_insn_after (gen_jump (label), after);
-      JUMP_LABEL (jump) = label;
-      LABEL_NUSES (label) += 1;
-
-      if (rtl_dump_file)
-       fprintf (rtl_dump_file, "Emitting jump to block %d (%d)\n",
-                bb->index, RBI (bb)->index);
-    }
-  else
-    {
-#ifdef HAVE_return
-      if (! HAVE_return)
-       abort ();
-      jump = emit_jump_insn_after (gen_return (), after);
-
-      if (rtl_dump_file)
-       fprintf (rtl_dump_file, "Emitting return\n");
-#else
-      abort ();
-#endif
-    }
-
-  return jump;
-}
-
-
-/* Given a reorder chain, rearrange the code to match.  */
-
-static void
-fixup_reorder_chain ()
-{
-  basic_block bb, last_bb;
-
-  /* First do the bulk reordering -- rechain the blocks without regard to
-     the needed changes to jumps and labels.  */
-
-  last_bb = BASIC_BLOCK (0);
-  bb = RBI (last_bb)->next;
-  while (bb)
-    {
-      rtx last_e = RBI (last_bb)->eff_end;
-      rtx curr_h = RBI (bb)->eff_head;
-
-      NEXT_INSN (last_e) = curr_h;
-      PREV_INSN (curr_h) = last_e;
-
-      last_bb = bb;
-      bb = RBI (bb)->next;
-    }
-  NEXT_INSN (RBI (last_bb)->eff_end) = NULL_RTX;
-  set_last_insn (RBI (last_bb)->eff_end);
-
-  /* Now add jumps and labels as needed to match the blocks new
-     outgoing edges.  */
-
-  for (bb = BASIC_BLOCK (0); bb ; bb = RBI (bb)->next)
-    {
-      edge e_fall, e_taken, e;
-      rtx jump_insn, barrier_insn, bb_end_insn;
-      basic_block nb;
-
-      if (bb->succ == NULL)
-       continue;
-
-      /* Find the old fallthru edge, and another non-EH edge for
-        a taken jump.  */
-      e_taken = e_fall = NULL;
-      for (e = bb->succ; e ; e = e->succ_next)
-       if (e->flags & EDGE_FALLTHRU)
-         e_fall = e;
-       else if (! (e->flags & EDGE_EH))
-         e_taken = e;
-
-      bb_end_insn = bb->end;
-      if (GET_CODE (bb_end_insn) == JUMP_INSN)
-       {
-         if (any_uncondjump_p (bb_end_insn))
-           {
-             /* If the destination is still not next, nothing to do.  */
-             if (RBI (bb)->index + 1 != RBI (e_taken->dest)->index)
-               continue;
-
-             /* Otherwise, we can remove the jump and cleanup the edge.  */
-             tidy_fallthru_edge (e_taken, bb, e_taken->dest);
-             RBI (bb)->eff_end = skip_insns_after_block (bb);
-             RBI (e_taken->dest)->eff_head = NEXT_INSN (RBI (bb)->eff_end);
-
-             if (rtl_dump_file)
-               fprintf (rtl_dump_file, "Removing jump in block %d (%d)\n",
-                        bb->index, RBI (bb)->index);
-             continue;
-           }
-         else if (any_condjump_p (bb_end_insn))
-           {
-             /* If the old fallthru is still next, nothing to do.  */
-             if (RBI (bb)->index + 1 == RBI (e_fall->dest)->index
-                 || (RBI (bb)->index == n_basic_blocks - 1
-                     && e_fall->dest == EXIT_BLOCK_PTR))
-               continue;
-
-             /* There is one special case: if *neither* block is next,
-                such as happens at the very end of a function, then we'll
-                need to add a new unconditional jump.  Choose the taken
-                edge based on known or assumed probability.  */
-             if (RBI (bb)->index + 1 != RBI (e_taken->dest)->index)
-               {
-                 rtx note = find_reg_note (bb_end_insn, REG_BR_PROB, 0);
-                 if (note
-                     && INTVAL (XEXP (note, 0)) < REG_BR_PROB_BASE / 2
-                     && invert_jump (bb_end_insn,
-                                     label_for_bb (e_fall->dest), 0))
-                   {
-                     e_fall->flags &= ~EDGE_FALLTHRU;
-                     e_taken->flags |= EDGE_FALLTHRU;
-                     e = e_fall, e_fall = e_taken, e_taken = e;
-                   }
-               }
-
-             /* Otherwise we can try to invert the jump.  This will 
-                basically never fail, however, keep up the pretense.  */
-             else if (invert_jump (bb_end_insn,
-                                   label_for_bb (e_fall->dest), 0))
-               {
-                 e_fall->flags &= ~EDGE_FALLTHRU;
-                 e_taken->flags |= EDGE_FALLTHRU;
-                 continue;
-               }
-           }
-         else if (returnjump_p (bb_end_insn))
-           continue;
-         else
-           {
-             /* Otherwise we have some switch or computed jump.  In the
-                99% case, there should not have been a fallthru edge.  */
-             if (! e_fall)
-               continue;
-#ifdef CASE_DROPS_THROUGH
-             /* Except for VAX.  Since we didn't have predication for the
-                tablejump, the fallthru block should not have moved.  */
-             if (RBI (bb)->index + 1 == RBI (e_fall->dest)->index)
-               continue;
-             bb_end_insn = skip_insns_after_block (bb);
-#else
-             abort ();
-#endif
-           }
-       }
-      else
-       {
-         /* No fallthru implies a noreturn function with EH edges, or
-            something similarly bizarre.  In any case, we don't need to
-            do anything.  */
-         if (! e_fall)
-           continue;
-
-         /* If the fallthru block is still next, nothing to do.  */
-         if (RBI (bb)->index + 1 == RBI (e_fall->dest)->index
-             || (RBI (bb)->index == n_basic_blocks - 1
-                 && e_fall->dest == EXIT_BLOCK_PTR))
-           continue;
-
-         /* We need a new jump insn.  If the block has only one outgoing
-            edge, then we can stuff the new jump insn in directly.  */
-         if (bb->succ->succ_next == NULL)
-           {
-             e_fall->flags &= ~EDGE_FALLTHRU;
-
-             jump_insn = emit_jump_to_block_after (e_fall->dest, bb_end_insn);
-             bb->end = jump_insn;
-             barrier_insn = emit_barrier_after (jump_insn);
-             RBI (bb)->eff_end = barrier_insn;
-             continue;
-           }
-       }
-
-      /* We got here if we need to add a new jump insn in a new block
-        across the edge e_fall.  */
-
-      jump_insn = emit_jump_to_block_after (e_fall->dest, bb_end_insn);
-      barrier_insn = emit_barrier_after (jump_insn);
-
-      VARRAY_GROW (basic_block_info, ++n_basic_blocks);
-      create_basic_block (n_basic_blocks - 1, jump_insn, jump_insn, NULL);
-
-      nb = BASIC_BLOCK (n_basic_blocks - 1);
-      nb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
-      nb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
-      nb->local_set = 0;
-
-      COPY_REG_SET (nb->global_live_at_start, bb->global_live_at_start);
-      COPY_REG_SET (nb->global_live_at_end, bb->global_live_at_start);
-
-      nb->aux = xmalloc (sizeof (struct reorder_block_def));
-      RBI (nb)->eff_head = nb->head;
-      RBI (nb)->eff_end = barrier_insn;
-      RBI (nb)->scope = RBI (bb)->scope;
-      RBI (nb)->index = RBI (bb)->index + 1;
-      RBI (nb)->visited = 1;
-      RBI (nb)->next = RBI (bb)->next;
-      RBI (bb)->next = nb;
-
-      /* Link to new block.  */
-      make_edge (NULL, nb, e_fall->dest, 0);
-      redirect_edge_succ (e_fall, nb);
-
-      /* Don't process this new block.  */
-      bb = nb;
-
-      /* Fix subsequent reorder block indices to reflect new block.  */
-      while ((nb = RBI (nb)->next) != NULL)
-       RBI (nb)->index += 1;
-    }
-
-  /* Put basic_block_info in the new order.  */
-  for (bb = BASIC_BLOCK (0); bb ; bb = RBI (bb)->next)
-    {
-      bb->index = RBI (bb)->index;
-      BASIC_BLOCK (bb->index) = bb;
-    }
-}
-
-
-/* Perform sanity checks on the insn chain.
-   1. Check that next/prev pointers are consistent in both the forward and
-      reverse direction.
-   2. Count insns in chain, going both directions, and check if equal.
-   3. Check that get_last_insn () returns the actual end of chain.  */
-
-void
-verify_insn_chain ()
-{
-  rtx x,
-      prevx,
-      nextx;
-  int insn_cnt1,
-      insn_cnt2;
-
-  prevx = NULL;
-  insn_cnt1 = 1;
-  for (x = get_insns (); x; x = NEXT_INSN (x))
-    {
-      if (PREV_INSN (x) != prevx)
-       {
-         fprintf (stderr, "Forward traversal: insn chain corrupt.\n");
-         fprintf (stderr, "previous insn:\n");
-         debug_rtx (prevx);
-         fprintf (stderr, "current insn:\n");
-         debug_rtx (x);
-         abort ();
-       }
-      ++insn_cnt1;
-      prevx = x;
-    }
-
-  if (prevx != get_last_insn ())
-    {
-      fprintf (stderr, "last_insn corrupt.\n");
-      abort ();
-    }
-
-  nextx = NULL;
-  insn_cnt2 = 1;
-  for (x = get_last_insn (); x; x = PREV_INSN (x))
-    {
-      if (NEXT_INSN (x) != nextx)
-       {
-         fprintf (stderr, "Reverse traversal: insn chain corrupt.\n");
-         fprintf (stderr, "current insn:\n");
-         debug_rtx (x);
-         fprintf (stderr, "next insn:\n");
-         debug_rtx (nextx);
-         abort ();
-       }
-      ++insn_cnt2;
-      nextx = x;
-    }
-
-  if (insn_cnt1 != insn_cnt2)
-    {
-      fprintf (stderr, "insn_cnt1 (%d) not equal to insn_cnt2 (%d).\n",
-              insn_cnt1, insn_cnt2);
-      abort ();
-    }
-}
-
-static rtx
-get_next_bb_note (x)
-     rtx x;
-{
-  while (x)
-    {
-      if (NOTE_INSN_BASIC_BLOCK_P (x))
-       return x;
-      x = NEXT_INSN (x);
-    }
-  return NULL;
-}
-
-
-static rtx
-get_prev_bb_note (x)
-     rtx x;
-{
-  while (x)
-    {
-      if (NOTE_INSN_BASIC_BLOCK_P (x))
-       return x;
-      x = PREV_INSN (x);
-    }
-  return NULL;
-}
-
-
-/* Determine and record the relationships between basic blocks and
-   scopes in scope tree S.  */
-
-static void
-relate_bbs_with_scopes (s)
-     scope s;
-{
-  scope p;
-  int i, bbi1, bbi2, bbs_spanned;
-  rtx bbnote;
-
-  for (p = s->inner; p; p = p->next)
-    relate_bbs_with_scopes (p);
-
-  bbi1 = bbi2 = -1;
-  bbs_spanned = 0;
-
-  /* If the begin and end notes are both inside the same basic block,
-     or if they are both outside of basic blocks, then we know immediately
-     how they are related. Otherwise, we need to poke around to make the
-     determination.  */
-  if (s->bb_beg != s->bb_end)
-    {
-      if (s->bb_beg && s->bb_end)
-        {
-         /* Both notes are in different bbs. This implies that all the
-            basic blocks spanned by the pair of notes are contained in
-             this scope.  */
-         bbi1 = s->bb_beg->index;
-         bbi2 = s->bb_end->index;
-         bbs_spanned = 1;
-       }
-      else if (! s->bb_beg)
-        {
-         /* First note is outside of a bb. If the scope spans more than
-            one basic block, then they all are contained within this
-             scope. Otherwise, this scope is contained within the basic
-            block.  */
-         bbnote = get_next_bb_note (s->note_beg);
-         if (! bbnote)
-           abort ();
-         if (NOTE_BASIC_BLOCK (bbnote) == s->bb_end)
-           {
-             bbs_spanned = 0;
-             s->bb_beg = NOTE_BASIC_BLOCK (bbnote);
-           }
-         else
-           {
-             bbi1 = NOTE_BASIC_BLOCK (bbnote)->index;
-             bbi2 = s->bb_end->index;
-             s->bb_end = NULL;
-             bbs_spanned = 1;
-           }
-       }
-      else /* ! s->bb_end */
-        {
-         /* Second note is outside of a bb. If the scope spans more than
-            one basic block, then they all are contained within this
-             scope. Otherwise, this scope is contained within the basic
-            block.  */
-         bbnote = get_prev_bb_note (s->note_end);
-         if (! bbnote)
-           abort ();
-         if (NOTE_BASIC_BLOCK (bbnote) == s->bb_beg)
-           {
-             bbs_spanned = 0;
-             s->bb_end = NOTE_BASIC_BLOCK (bbnote);
-           }
-         else
-           {
-             bbi1 = s->bb_beg->index;
-             bbi2 = NOTE_BASIC_BLOCK (bbnote)->index;
-             s->bb_beg = NULL;
-             bbs_spanned = 1;
-           }
-       }
-    }
-  else
-    {
-      if (s->bb_beg)
-        /* Both notes are in the same bb, which implies the block
-          contains this scope.  */
-       bbs_spanned = 0;
-      else
-       {
-          rtx x1, x2;
-         /* Both notes are outside of any bbs. This implies that all the
-            basic blocks spanned by the pair of notes are contained in
-             this scope. 
-            There is a degenerate case to consider. If the notes do not
-            span any basic blocks, then it is an empty scope that can
-            safely be deleted or ignored. Mark these with level = -1.  */
-
-         x1 = get_next_bb_note (s->note_beg);
-         x2 = get_prev_bb_note (s->note_end);
-         if (! (x1 && x2))
-           {
-             s->level = -1; 
-             bbs_spanned = 0; 
-           }
-         else
-           {
-             bbi1 = NOTE_BASIC_BLOCK (x1)->index;
-             bbi2 = NOTE_BASIC_BLOCK (x2)->index;
-             bbs_spanned = 1;
-           }
-       }
-    }
-
-  /* If the scope spans one or more basic blocks, we record them. We
-     only record the bbs that are immediately contained within this
-     scope. Note that if a scope is contained within a bb, we can tell
-     by checking that bb_beg = bb_end and that they are non-null.  */
-  if (bbs_spanned)
-    {
-      int j = 0;
-
-      s->num_bbs = 0;
-      for (i = bbi1; i <= bbi2; i++)
-       if (! RBI (BASIC_BLOCK (i))->scope)
-         s->num_bbs++;
-
-      s->bbs = xmalloc (s->num_bbs * sizeof (basic_block));
-      for (i = bbi1; i <= bbi2; i++)
-       {
-         basic_block curr_bb = BASIC_BLOCK (i);
-         if (! RBI (curr_bb)->scope)
-           {
-             s->bbs[j++] = curr_bb;
-             RBI (curr_bb)->scope = s;
-           }
-       }
-    }
-  else
-    s->num_bbs = 0;
-}
-
-
-/* Allocate and initialize a new scope structure with scope level LEVEL,
-   and record the NOTE beginning the scope.  */
-
-static scope 
-make_new_scope (level, note)
-     int level;
-     rtx note;
-{
-  scope new_scope = xcalloc (1, sizeof (struct scope_def));
-  new_scope->level = level;
-  new_scope->note_beg = note;
-  return new_scope;
-}
-
-
-/* Build a forest representing the scope structure of the function.
-   Return a pointer to a structure describing the forest.  */
-
-static void
-build_scope_forest (forest)
-    scope_forest_info *forest;
-{
-  rtx x;
-  int level, bbi, i;
-  basic_block curr_bb;
-  scope root, curr_scope = 0;
-
-  forest->num_trees = 0;
-  forest->trees = NULL;
-  level = -1;
-  root = NULL;
-  curr_bb = NULL;
-  bbi = 0;
-  for (x = get_insns (); x; x = NEXT_INSN (x))
-    {
-      if (bbi < n_basic_blocks && x == BASIC_BLOCK (bbi)->head)
-       curr_bb = BASIC_BLOCK (bbi);
-
-      if (GET_CODE (x) == NOTE)
-       {
-         if (NOTE_LINE_NUMBER (x) == NOTE_INSN_BLOCK_BEG)
-           {
-             if (root)
-               {
-                 scope new_scope;
-                 if (! curr_scope)
-                   abort();
-                 level++;
-                 new_scope = make_new_scope (level, x);
-                 new_scope->outer = curr_scope;
-                 new_scope->next = NULL;
-                 if (! curr_scope->inner)
-                   {
-                     curr_scope->inner = new_scope;
-                     curr_scope->inner_last = new_scope;
-                   }
-                 else
-                   {
-                     curr_scope->inner_last->next = new_scope;
-                     curr_scope->inner_last = new_scope;
-                   }
-                 curr_scope = curr_scope->inner_last;
-               }
-             else
-               {
-                 int ntrees = forest->num_trees;
-                 level++;
-                 curr_scope = make_new_scope (level, x);
-                 root = curr_scope;
-                 forest->trees = xrealloc (forest->trees,
-                                           sizeof (scope) * (ntrees + 1));
-                 forest->trees[forest->num_trees++] = root;
-               }
-             curr_scope->bb_beg = curr_bb;
-           }
-         else if (NOTE_LINE_NUMBER (x) == NOTE_INSN_BLOCK_END)
-           {
-             curr_scope->bb_end = curr_bb;
-             curr_scope->note_end = x;
-             level--;
-             curr_scope = curr_scope->outer;
-             if (level == -1)
-               root = NULL;
-           }
-       } /* if note */
-
-      if (curr_bb && curr_bb->end == x)
-       {
-         curr_bb = NULL;
-         bbi++;
-       }
-
-    } /* for */
-
-  for (i = 0; i < forest->num_trees; i++)
-    relate_bbs_with_scopes (forest->trees[i]);
-}
-
-
-/* Remove all the NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes from
-   the insn chain.  */
-
-static void
-remove_scope_notes ()
-{
-  rtx x, next;
-  basic_block currbb = NULL;
-
-  for (x = get_insns (); x; x = next)
-    {
-      next = NEXT_INSN (x);
-      if (NOTE_INSN_BASIC_BLOCK_P (x))
-       currbb = NOTE_BASIC_BLOCK (x);
-
-      if (GET_CODE (x) == NOTE
-         && (NOTE_LINE_NUMBER (x) == NOTE_INSN_BLOCK_BEG
-             || NOTE_LINE_NUMBER (x) == NOTE_INSN_BLOCK_END))
-       {
-         /* Check if the scope note happens to be the end of a bb.  */
-         if (currbb && x == currbb->end)
-           currbb->end = PREV_INSN (x);
-         if (currbb && x == currbb->head)
-           abort ();
-
-         if (PREV_INSN (x))
-           {
-             NEXT_INSN (PREV_INSN (x)) = next;
-             PREV_INSN (next) = PREV_INSN (x);
-
-              NEXT_INSN (x) = NULL;
-              PREV_INSN (x) = NULL;
-           }
-         else
-           abort ();
-       }
-    }
-}
-
-
-/* Insert scope note pairs for a contained scope tree S after insn IP.  */
-
-static void
-insert_intra_1 (s, ip)
-     scope s;
-     rtx *ip;
-{
-  scope p;
-
-  if (NOTE_BLOCK (s->note_beg))
-    {  
-      *ip = emit_note_after (NOTE_INSN_BLOCK_BEG, *ip);
-      NOTE_BLOCK (*ip) = NOTE_BLOCK (s->note_beg);
-    } 
-
-  for (p = s->inner; p; p = p->next)
-    insert_intra_1 (p, ip);
-
-  if (NOTE_BLOCK (s->note_beg))
-    {  
-      *ip = emit_note_after (NOTE_INSN_BLOCK_END, *ip);
-      NOTE_BLOCK (*ip) = NOTE_BLOCK (s->note_end);
-    }
-}
-
-
-/* Insert NOTE_INSN_BLOCK_END notes and NOTE_INSN_BLOCK_BEG notes for
-   scopes that are contained within BB.  */
-
-static void
-insert_intra_bb_scope_notes (bb)
-     basic_block bb;
-{
-  scope s = RBI (bb)->scope;
-  scope p;
-  rtx ip;
-
-  if (! s)
-    return;
-
-  ip = bb->head;
-  if (GET_CODE (ip) == CODE_LABEL)
-    ip = NEXT_INSN (ip);
-
-  for (p = s->inner; p; p = p->next)
-    {
-      if (p->bb_beg != NULL && p->bb_beg == p->bb_end && p->bb_beg == bb)
-       insert_intra_1 (p, &ip);
-    }
-}
-
-
-/* Given two consecutive basic blocks BB1 and BB2 with different scopes,
-   insert NOTE_INSN_BLOCK_END notes after BB1 and NOTE_INSN_BLOCK_BEG
-   notes before BB2 such that the notes are correctly balanced. If BB1 or
-   BB2 is NULL, we are inserting scope notes for the first and last basic
-   blocks, respectively.  */
-
-static void
-insert_inter_bb_scope_notes (bb1, bb2)
-     basic_block bb1;
-     basic_block bb2;
-{
-  rtx ip;
-  scope com;
-
-  /* It is possible that a basic block is not contained in any scope.
-     In that case, we either open or close a scope but not both.  */
-  if (bb1 && bb2)
-    {
-      scope s1 = RBI (bb1)->scope;
-      scope s2 = RBI (bb2)->scope;
-      if (! s1 && ! s2)
-       return;
-      if (! s1)
-       bb1 = NULL;
-      else if (! s2)
-       bb2 = NULL;
-    }
-
-  /* Find common ancestor scope.  */
-  if (bb1 && bb2)
-    {
-      scope s1 = RBI (bb1)->scope;
-      scope s2 = RBI (bb2)->scope;
-      while (s1 != s2)
-       {
-          if (! (s1 && s2))
-           abort ();
-         if (s1->level > s2->level)
-           s1 = s1->outer;
-         else if (s2->level > s1->level)
-           s2 = s2->outer;
-         else
-           {
-             s1 = s1->outer;
-             s2 = s2->outer;
-           }
-       }
-      com = s1;
-    }
-  else
-    com = NULL;
-
-  /* Close scopes.  */
-  if (bb1)
-    {
-      scope s = RBI (bb1)->scope;
-      ip = RBI (bb1)->eff_end;
-      while (s != com)
-       {
-         if (NOTE_BLOCK (s->note_beg))
-           {  
-             ip = emit_note_after (NOTE_INSN_BLOCK_END, ip);
-             NOTE_BLOCK (ip) = NOTE_BLOCK (s->note_end);
-           }
-         s = s->outer;
-       }
-    }
-
-  /* Open scopes.  */
-  if (bb2)
-    {
-      scope s = RBI (bb2)->scope;
-      ip = bb2->head;
-      while (s != com)
-       {
-         if (NOTE_BLOCK (s->note_beg))
-           {  
-             ip = emit_note_before (NOTE_INSN_BLOCK_BEG, ip);
-             NOTE_BLOCK (ip) = NOTE_BLOCK (s->note_beg);
-           }
-         s = s->outer;
-       }
-    }
-}
-
-
-/* Rebuild all the NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes based
-   on the scope forest and the newly reordered basic blocks.  */
-
-static void
-rebuild_scope_notes (forest)
-    scope_forest_info *forest;
-{
-  int i;
-
-  if (forest->num_trees == 0)
-    return;
-
-  /* Start by opening the scopes before the first basic block.  */
-  insert_inter_bb_scope_notes (NULL, BASIC_BLOCK (0));
-
-  /* Then, open and close scopes as needed between blocks.  */
-  for (i = 0; i < n_basic_blocks - 1; i++)
-    {
-      basic_block bb1 = BASIC_BLOCK (i);
-      basic_block bb2 = BASIC_BLOCK (i + 1);
-      if (RBI (bb1)->scope != RBI (bb2)->scope)
-       insert_inter_bb_scope_notes (bb1, bb2);
-      insert_intra_bb_scope_notes (bb1);
-    }
-
-  /* Finally, close the scopes after the last basic block.  */
-  insert_inter_bb_scope_notes (BASIC_BLOCK (n_basic_blocks - 1), NULL);
-  insert_intra_bb_scope_notes (BASIC_BLOCK (n_basic_blocks - 1));
-}
-
-
-/* Free the storage associated with the scope tree at S.  */
-
-static void
-free_scope_forest_1 (s)
-    scope s;
-{
-  scope p, next;
-
-  for (p = s->inner; p; p = next)
-    {
-      next = p->next;
-      free_scope_forest_1 (p);
-    }
-
-  if (s->bbs)
-    free (s->bbs);
-  free (s);
-}
-
-
-/* Free the storage associated with the scope forest.  */
-
-static void
-free_scope_forest (forest)
-    scope_forest_info *forest;
-{
-  int i;
-  for (i = 0; i < forest->num_trees; i++)
-    free_scope_forest_1 (forest->trees[i]);
-}
-
-
-/* Visualize the scope forest.  */
-
-void
-dump_scope_forest (forest)
-    scope_forest_info *forest;
-{
-  if (forest->num_trees == 0)
-    fprintf (stderr, "\n< Empty scope forest >\n");
-  else
-    {
-      int i;
-      fprintf (stderr, "\n< Scope forest >\n");
-      for (i = 0; i < forest->num_trees; i++)
-       dump_scope_forest_1 (forest->trees[i], 0);
-    }
-}
-
-
-/* Recursive portion of dump_scope_forest.  */
-
-static void
-dump_scope_forest_1 (s, indent)
-     scope s;
-     int indent;
-{
-  scope p;
-  int i;
-
-  if (s->bb_beg != NULL && s->bb_beg == s->bb_end
-      && RBI (s->bb_beg)->scope
-      && RBI (s->bb_beg)->scope->level + 1 == s->level)
-    {
-      fprintf (stderr, "%*s", indent, "");
-      fprintf (stderr, "BB%d:\n", s->bb_beg->index);
-    }
-
-  fprintf (stderr, "%*s", indent, "");
-  fprintf (stderr, "{ level %d (block %p)\n", s->level,
-          (PTR) NOTE_BLOCK (s->note_beg));
-
-  fprintf (stderr, "%*s%s", indent, "", "bbs:");
-  for (i = 0; i < s->num_bbs; i++)
-    fprintf (stderr, " %d", s->bbs[i]->index);
-  fprintf (stderr, "\n");
-  
-  for (p = s->inner; p; p = p->next)
-    dump_scope_forest_1 (p, indent + 2);
-
-  fprintf (stderr, "%*s", indent, "");
-  fprintf (stderr, "}\n");
-}
-
-
 /* Reorder basic blocks.  The main entry point to this file.  */
 
 void
 reorder_basic_blocks ()
 {
-  scope_forest_info forest;
-  int i;
-
   if (n_basic_blocks <= 1)
     return;
 
-  for (i = 0; i < n_basic_blocks; i++)
-    BASIC_BLOCK (i)->aux = xcalloc (1, sizeof (struct reorder_block_def));
-
-  EXIT_BLOCK_PTR->aux = xcalloc (1, sizeof (struct reorder_block_def));
-
-  build_scope_forest (&forest);
-  remove_scope_notes ();
+  cfg_layout_initialize ();
 
-  record_effective_endpoints ();
   make_reorder_chain ();
-  fixup_reorder_chain ();
 
-#ifdef ENABLE_CHECKING
-  verify_insn_chain ();
-#endif
-
-  rebuild_scope_notes (&forest);
-  free_scope_forest (&forest);
-  reorder_blocks ();
-
-  for (i = 0; i < n_basic_blocks; i++)
-    free (BASIC_BLOCK (i)->aux);
+  if (rtl_dump_file)
+    dump_flow_info (rtl_dump_file);
 
-  free (EXIT_BLOCK_PTR->aux);
-
-#ifdef ENABLE_CHECKING
-  verify_flow_info ();
-#endif
+  cfg_layout_finalize ();
 }