]> oss.titaniummirror.com Git - msp430-gcc.git/blobdiff - gcc/cfgbuild.c
Imported gcc-4.4.3
[msp430-gcc.git] / gcc / cfgbuild.c
index 3a5af2dd2b29d9d12e8b0c5f9917c90b334cb2fb..519108e51dc6f94bbae8e96f8e135718ce8b24a8 100644 (file)
@@ -1,12 +1,13 @@
 /* Control flow graph building code for GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 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
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -15,9 +16,8 @@ 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 GCC; 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 COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* find_basic_blocks divides the current function's rtl into basic
    blocks and constructs the CFG.  The blocks are recorded in the
@@ -28,12 +28,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
    Available functionality:
      - CFG construction
-         find_basic_blocks
-     - Local CFG construction
-         find_sub_basic_blocks          */
+        find_basic_blocks  */
 \f
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "tree.h"
 #include "rtl.h"
 #include "hard-reg-set.h"
@@ -45,32 +45,26 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "except.h"
 #include "toplev.h"
 #include "timevar.h"
-#include "obstack.h"
-
-static int count_basic_blocks          PARAMS ((rtx));
-static void find_basic_blocks_1                PARAMS ((rtx));
-static rtx find_label_refs             PARAMS ((rtx, rtx));
-static void make_edges                 PARAMS ((rtx, int, int, int));
-static void make_label_edge            PARAMS ((sbitmap *, basic_block,
-                                                rtx, int));
-static void make_eh_edge               PARAMS ((sbitmap *, basic_block, rtx));
-static void find_bb_boundaries         PARAMS ((basic_block));
-static void compute_outgoing_frequencies PARAMS ((basic_block));
-static bool inside_basic_block_p       PARAMS ((rtx));
+
+static int count_basic_blocks (const_rtx);
+static void find_basic_blocks_1 (rtx);
+static void make_edges (basic_block, basic_block, int);
+static void make_label_edge (sbitmap, basic_block, rtx, int);
+static void find_bb_boundaries (basic_block);
+static void compute_outgoing_frequencies (basic_block);
 \f
 /* Return true if insn is something that should be contained inside basic
    block.  */
 
-static bool
-inside_basic_block_p (insn)
-     rtx insn;
+bool
+inside_basic_block_p (const_rtx insn)
 {
   switch (GET_CODE (insn))
     {
     case CODE_LABEL:
       /* Avoid creating of basic block for jumptables.  */
       return (NEXT_INSN (insn) == 0
-             || GET_CODE (NEXT_INSN (insn)) != JUMP_INSN
+             || !JUMP_P (NEXT_INSN (insn))
              || (GET_CODE (PATTERN (NEXT_INSN (insn))) != ADDR_VEC
                  && GET_CODE (PATTERN (NEXT_INSN (insn))) != ADDR_DIFF_VEC));
 
@@ -87,7 +81,7 @@ inside_basic_block_p (insn)
       return false;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -95,60 +89,69 @@ inside_basic_block_p (insn)
    the basic block.  */
 
 bool
-control_flow_insn_p (insn)
-     rtx insn;
+control_flow_insn_p (const_rtx insn)
 {
   rtx note;
 
   switch (GET_CODE (insn))
     {
-      case NOTE:
-      case CODE_LABEL:
-       return false;
-
-      case JUMP_INSN:
-       /* Jump insn always causes control transfer except for tablejumps.  */
-       return (GET_CODE (PATTERN (insn)) != ADDR_VEC
-               && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC);
-
-      case CALL_INSN:
-       /* Call insn may return to the nonlocal goto handler.  */
-       return ((nonlocal_goto_handler_labels
-                && (0 == (note = find_reg_note (insn, REG_EH_REGION,
-                                                NULL_RTX))
-                    || INTVAL (XEXP (note, 0)) >= 0))
-               /* Or may trap.  */
-               || can_throw_internal (insn));
-
-      case INSN:
-       return (flag_non_call_exceptions && can_throw_internal (insn));
-
-      case BARRIER:
-       /* It is nonsence to reach barrier when looking for the
-          end of basic block, but before dead code is eliminated
-          this may happen.  */
-       return false;
-
-      default:
-       abort ();
+    case NOTE:
+    case CODE_LABEL:
+      return false;
+
+    case JUMP_INSN:
+      /* Jump insn always causes control transfer except for tablejumps.  */
+      return (GET_CODE (PATTERN (insn)) != ADDR_VEC
+             && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC);
+
+    case CALL_INSN:
+      /* Noreturn and sibling call instructions terminate the basic blocks
+        (but only if they happen unconditionally).  */
+      if ((SIBLING_CALL_P (insn)
+          || find_reg_note (insn, REG_NORETURN, 0))
+         && GET_CODE (PATTERN (insn)) != COND_EXEC)
+       return true;
+      /* Call insn may return to the nonlocal goto handler.  */
+      return ((nonlocal_goto_handler_labels
+              && (0 == (note = find_reg_note (insn, REG_EH_REGION,
+                                              NULL_RTX))
+                  || INTVAL (XEXP (note, 0)) >= 0))
+             /* Or may trap.  */
+             || can_throw_internal (insn));
+
+    case INSN:
+      /* Treat trap instructions like noreturn calls (same provision).  */
+      if (GET_CODE (PATTERN (insn)) == TRAP_IF
+         && XEXP (PATTERN (insn), 0) == const1_rtx)
+       return true;
+
+      return (flag_non_call_exceptions && can_throw_internal (insn));
+
+    case BARRIER:
+      /* It is nonsense to reach barrier when looking for the
+        end of basic block, but before dead code is eliminated
+        this may happen.  */
+      return false;
+
+    default:
+      gcc_unreachable ();
     }
 }
 
 /* Count the basic blocks of the function.  */
 
 static int
-count_basic_blocks (f)
-     rtx f;
+count_basic_blocks (const_rtx f)
 {
-  int count = 0;
+  int count = NUM_FIXED_BLOCKS;
   bool saw_insn = false;
-  rtx insn;
+  const_rtx insn;
 
   for (insn = f; insn; insn = NEXT_INSN (insn))
     {
-      /* Code labels and barriers causes curent basic block to be
-         terminated at previous real insn.  */
-      if ((GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == BARRIER)
+      /* Code labels and barriers causes current basic block to be
+        terminated at previous real insn.  */
+      if ((LABEL_P (insn) || BARRIER_P (insn))
          && saw_insn)
        count++, saw_insn = false;
 
@@ -166,61 +169,14 @@ count_basic_blocks (f)
 
   /* The rest of the compiler works a bit smoother when we don't have to
      check for the edge case of do-nothing functions with no basic blocks.  */
-  if (count == 0)
+  if (count == NUM_FIXED_BLOCKS)
     {
-      emit_insn (gen_rtx_USE (VOIDmode, const0_rtx));
-      count = 1;
+      emit_use (const0_rtx);
+      count = NUM_FIXED_BLOCKS + 1;
     }
 
   return count;
 }
-
-/* Scan a list of insns for labels referred to other than by jumps.
-   This is used to scan the alternatives of a call placeholder.  */
-
-static rtx
-find_label_refs (f, lvl)
-     rtx f;
-     rtx lvl;
-{
-  rtx insn;
-
-  for (insn = f; insn; insn = NEXT_INSN (insn))
-    if (INSN_P (insn) && GET_CODE (insn) != JUMP_INSN)
-      {
-       rtx note;
-
-       /* Make a list of all labels referred to other than by jumps
-          (which just don't have the REG_LABEL notes).
-
-          Make a special exception for labels followed by an ADDR*VEC,
-          as this would be a part of the tablejump setup code.
-
-          Make a special exception to registers loaded with label
-          values just before jump insns that use them.  */
-
-       for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
-         if (REG_NOTE_KIND (note) == REG_LABEL)
-           {
-             rtx lab = XEXP (note, 0), next;
-
-             if ((next = next_nonnote_insn (lab)) != NULL
-                      && GET_CODE (next) == JUMP_INSN
-                      && (GET_CODE (PATTERN (next)) == ADDR_VEC
-                          || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
-               ;
-             else if (GET_CODE (lab) == NOTE)
-               ;
-             else if (GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
-                      && find_reg_note (NEXT_INSN (insn), REG_LABEL, lab))
-               ;
-             else
-               lvl = alloc_EXPR_LIST (0, XEXP (note, 0), lvl);
-           }
-      }
-
-  return lvl;
-}
 \f
 /* Create an edge between two basic blocks.  FLAGS are auxiliary information
    about the edge that is accumulated between calls.  */
@@ -228,14 +184,9 @@ find_label_refs (f, lvl)
 /* Create an edge from a basic block to a label.  */
 
 static void
-make_label_edge (edge_cache, src, label, flags)
-     sbitmap *edge_cache;
-     basic_block src;
-     rtx label;
-     int flags;
+make_label_edge (sbitmap edge_cache, basic_block src, rtx label, int flags)
 {
-  if (GET_CODE (label) != CODE_LABEL)
-    abort ();
+  gcc_assert (LABEL_P (label));
 
   /* If the label was never emitted, this insn is junk, but avoid a
      crash trying to refer to BLOCK_FOR_INSN (label).  This can happen
@@ -250,13 +201,10 @@ make_label_edge (edge_cache, src, label, flags)
 
 /* Create the edges generated by INSN in REGION.  */
 
-static void
-make_eh_edge (edge_cache, src, insn)
-     sbitmap *edge_cache;
-     basic_block src;
-     rtx insn;
+void
+rtl_make_eh_edge (sbitmap edge_cache, basic_block src, rtx insn)
 {
-  int is_call = GET_CODE (insn) == CALL_INSN ? EDGE_ABNORMAL_CALL : 0;
+  int is_call = CALL_P (insn) ? EDGE_ABNORMAL_CALL : 0;
   rtx handlers, i;
 
   handlers = reachable_handlers (insn);
@@ -268,63 +216,85 @@ make_eh_edge (edge_cache, src, insn)
   free_INSN_LIST_list (&handlers);
 }
 
-/* Identify the edges between basic blocks MIN to MAX.
+/* States of basic block as seen by find_many_sub_basic_blocks.  */
+enum state {
+  /* Basic blocks created via split_block belong to this state.
+     make_edges will examine these basic blocks to see if we need to
+     create edges going out of them.  */
+  BLOCK_NEW = 0,
+
+  /* Basic blocks that do not need examining belong to this state.
+     These blocks will be left intact.  In particular, make_edges will
+     not create edges going out of these basic blocks.  */
+  BLOCK_ORIGINAL,
+
+  /* Basic blocks that may need splitting (due to a label appearing in
+     the middle, etc) belong to this state.  After splitting them,
+     make_edges will create edges going out of them as needed.  */
+  BLOCK_TO_SPLIT
+};
 
-   NONLOCAL_LABEL_LIST is a list of non-local labels in the function.  Blocks
-   that are otherwise unreachable may be reachable with a non-local goto.
+#define STATE(BB) (enum state) ((size_t) (BB)->aux)
+#define SET_STATE(BB, STATE) ((BB)->aux = (void *) (size_t) (STATE))
 
-   BB_EH_END is an array indexed by basic block number in which we record
-   the list of exception regions active at the end of the basic block.  */
+/* Used internally by purge_dead_tablejump_edges, ORed into state.  */
+#define BLOCK_USED_BY_TABLEJUMP                32
+#define FULL_STATE(BB) ((size_t) (BB)->aux)
+
+/* Identify the edges going out of basic blocks between MIN and MAX,
+   inclusive, that have their states set to BLOCK_NEW or
+   BLOCK_TO_SPLIT.
+
+   UPDATE_P should be nonzero if we are updating CFG and zero if we
+   are building CFG from scratch.  */
 
 static void
-make_edges (label_value_list, min, max, update_p)
-     rtx label_value_list;
-     int min, max, update_p;
+make_edges (basic_block min, basic_block max, int update_p)
 {
-  int i;
-  sbitmap *edge_cache = NULL;
-
-  /* Assume no computed jump; revise as we create edges.  */
-  current_function_has_computed_jump = 0;
+  basic_block bb;
+  sbitmap edge_cache = NULL;
 
   /* Heavy use of computed goto in machine-generated code can lead to
      nearly fully-connected CFGs.  In that case we spend a significant
      amount of time searching the edge lists for duplicates.  */
-  if (forced_labels || label_value_list)
-    {
-      edge_cache = sbitmap_vector_alloc (n_basic_blocks, n_basic_blocks);
-      sbitmap_vector_zero (edge_cache, n_basic_blocks);
-
-      if (update_p)
-       for (i = min; i <= max; ++i)
-         {
-           edge e;
+  if (forced_labels || cfun->cfg->max_jumptable_ents > 100)
+    edge_cache = sbitmap_alloc (last_basic_block);
 
-           for (e = BASIC_BLOCK (i)->succ; e ; e = e->succ_next)
-             if (e->dest != EXIT_BLOCK_PTR)
-               SET_BIT (edge_cache[i], e->dest->index);
-         }
-    }
+  /* By nature of the way these get numbered, ENTRY_BLOCK_PTR->next_bb block
+     is always the entry.  */
+  if (min == ENTRY_BLOCK_PTR->next_bb)
+    make_edge (ENTRY_BLOCK_PTR, min, EDGE_FALLTHRU);
 
-  /* By nature of the way these get numbered, block 0 is always the entry.  */
-  if (min == 0)
-    cached_make_edge (edge_cache, ENTRY_BLOCK_PTR, BASIC_BLOCK (0),
-                     EDGE_FALLTHRU);
-
-  for (i = min; i <= max; ++i)
+  FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
     {
-      basic_block bb = BASIC_BLOCK (i);
       rtx insn, x;
       enum rtx_code code;
-      int force_fallthru = 0;
+      edge e;
+      edge_iterator ei;
 
-      if (GET_CODE (bb->head) == CODE_LABEL && LABEL_ALTERNATE_NAME (bb->head))
+      if (STATE (bb) == BLOCK_ORIGINAL)
+       continue;
+
+      /* If we have an edge cache, cache edges going out of BB.  */
+      if (edge_cache)
+       {
+         sbitmap_zero (edge_cache);
+         if (update_p)
+           {
+             FOR_EACH_EDGE (e, ei, bb->succs)
+               if (e->dest != EXIT_BLOCK_PTR)
+                 SET_BIT (edge_cache, e->dest->index);
+           }
+       }
+
+      if (LABEL_P (BB_HEAD (bb))
+         && LABEL_ALT_ENTRY_P (BB_HEAD (bb)))
        cached_make_edge (NULL, ENTRY_BLOCK_PTR, bb, 0);
 
       /* Examine the last instruction of the block, and discover the
         ways we can leave the block.  */
 
-      insn = bb->end;
+      insn = BB_END (bb);
       code = GET_CODE (insn);
 
       /* A branch.  */
@@ -334,19 +304,15 @@ make_edges (label_value_list, min, max, update_p)
 
          /* Recognize exception handling placeholders.  */
          if (GET_CODE (PATTERN (insn)) == RESX)
-           make_eh_edge (edge_cache, bb, insn);
+           rtl_make_eh_edge (edge_cache, bb, insn);
 
          /* Recognize a non-local goto as a branch outside the
             current function.  */
          else if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
            ;
 
-         /* ??? Recognize a tablejump and do the right thing.  */
-         else if ((tmp = JUMP_LABEL (insn)) != NULL_RTX
-                  && (tmp = NEXT_INSN (tmp)) != NULL_RTX
-                  && GET_CODE (tmp) == JUMP_INSN
-                  && (GET_CODE (PATTERN (tmp)) == ADDR_VEC
-                      || GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC))
+         /* Recognize a tablejump and do the right thing.  */
+         else if (tablejump_p (insn, NULL, &tmp))
            {
              rtvec vec;
              int j;
@@ -369,23 +335,12 @@ make_edges (label_value_list, min, max, update_p)
                  && GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF)
                make_label_edge (edge_cache, bb,
                                 XEXP (XEXP (SET_SRC (tmp), 2), 0), 0);
-
-#ifdef CASE_DROPS_THROUGH
-             /* Silly VAXen.  The ADDR_VEC is going to be in the way of
-                us naturally detecting fallthru into the next block.  */
-             force_fallthru = 1;
-#endif
            }
 
          /* If this is a computed jump, then mark it as reaching
-            everything on the label_value_list and forced_labels list.  */
+            everything on the forced_labels list.  */
          else if (computed_jump_p (insn))
            {
-             current_function_has_computed_jump = 1;
-
-             for (x = label_value_list; x; x = XEXP (x, 1))
-               make_label_edge (edge_cache, bb, XEXP (x, 0), EDGE_ABNORMAL);
-
              for (x = forced_labels; x; x = XEXP (x, 1))
                make_label_edge (edge_cache, bb, XEXP (x, 0), EDGE_ABNORMAL);
            }
@@ -397,8 +352,7 @@ make_edges (label_value_list, min, max, update_p)
          /* Otherwise, we have a plain conditional or unconditional jump.  */
          else
            {
-             if (! JUMP_LABEL (insn))
-               abort ();
+             gcc_assert (JUMP_LABEL (insn));
              make_label_edge (edge_cache, bb, JUMP_LABEL (insn), 0);
            }
        }
@@ -409,7 +363,7 @@ make_edges (label_value_list, min, max, update_p)
         in the first place.  */
       if (code == CALL_INSN && SIBLING_CALL_P (insn))
        cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR,
-                  EDGE_ABNORMAL | EDGE_ABNORMAL_CALL);
+                         EDGE_SIBCALL | EDGE_ABNORMAL);
 
       /* If this is a CALL_INSN, then mark it as reaching the active EH
         handler for this CALL_INSN.  If we're handling non-call
@@ -418,7 +372,7 @@ make_edges (label_value_list, min, max, update_p)
       else if (code == CALL_INSN || flag_non_call_exceptions)
        {
          /* Add any appropriate EH edges.  */
-         make_eh_edge (edge_cache, bb, insn);
+         rtl_make_eh_edge (edge_cache, bb, insn);
 
          if (code == CALL_INSN && nonlocal_goto_handler_labels)
            {
@@ -441,17 +395,22 @@ make_edges (label_value_list, min, max, update_p)
        }
 
       /* Find out if we can drop through to the next block.  */
-      insn = next_nonnote_insn (insn);
-      if (!insn || (i + 1 == n_basic_blocks && force_fallthru))
+      insn = NEXT_INSN (insn);
+      e = find_edge (bb, EXIT_BLOCK_PTR);
+      if (e && e->flags & EDGE_FALLTHRU)
+       insn = NULL;
+
+      while (insn
+            && NOTE_P (insn)
+            && NOTE_KIND (insn) != NOTE_INSN_BASIC_BLOCK)
+       insn = NEXT_INSN (insn);
+
+      if (!insn)
        cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR, EDGE_FALLTHRU);
-      else if (i + 1 < n_basic_blocks)
+      else if (bb->next_bb != EXIT_BLOCK_PTR)
        {
-         rtx tmp = BLOCK_HEAD (i + 1);
-         if (GET_CODE (tmp) == NOTE)
-           tmp = next_nonnote_insn (tmp);
-         if (force_fallthru || insn == tmp)
-           cached_make_edge (edge_cache, bb, BASIC_BLOCK (i + 1),
-                             EDGE_FALLTHRU);
+         if (insn == BB_HEAD (bb->next_bb))
+           cached_make_edge (edge_cache, bb, bb->next_bb, EDGE_FALLTHRU);
        }
     }
 
@@ -465,16 +424,13 @@ make_edges (label_value_list, min, max, update_p)
    will be used in make_edges for use with computed gotos.  */
 
 static void
-find_basic_blocks_1 (f)
-     rtx f;
+find_basic_blocks_1 (rtx f)
 {
   rtx insn, next;
-  int i = 0;
   rtx bb_note = NULL_RTX;
-  rtx lvl = NULL_RTX;
-  rtx trll = NULL_RTX;
   rtx head = NULL_RTX;
   rtx end = NULL_RTX;
+  basic_block prev = ENTRY_BLOCK_PTR;
 
   /* We process the instructions in a slightly different way than we did
      previously.  This is so that we see a NOTE_BASIC_BLOCK after we have
@@ -488,10 +444,10 @@ find_basic_blocks_1 (f)
 
       next = NEXT_INSN (insn);
 
-      if ((GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == BARRIER)
+      if ((LABEL_P (insn) || BARRIER_P (insn))
          && head)
        {
-         create_basic_block_structure (i++, head, end, bb_note);
+         prev = create_basic_block_structure (head, end, bb_note, prev);
          head = end = NULL_RTX;
          bb_note = NULL_RTX;
        }
@@ -505,7 +461,7 @@ find_basic_blocks_1 (f)
 
       if (head && control_flow_insn_p (insn))
        {
-         create_basic_block_structure (i++, head, end, bb_note);
+         prev = create_basic_block_structure (head, end, bb_note, prev);
          head = end = NULL_RTX;
          bb_note = NULL_RTX;
        }
@@ -513,124 +469,71 @@ find_basic_blocks_1 (f)
       switch (code)
        {
        case NOTE:
-         {
-           int kind = NOTE_LINE_NUMBER (insn);
-
-           /* Look for basic block notes with which to keep the
-              basic_block_info pointers stable.  Unthread the note now;
-              we'll put it back at the right place in create_basic_block.
-              Or not at all if we've already found a note in this block.  */
-           if (kind == NOTE_INSN_BASIC_BLOCK)
-             {
-               if (bb_note == NULL_RTX)
-                 bb_note = insn;
-               else
-                 next = delete_insn (insn);
-             }
-           break;
-         }
+         /* Look for basic block notes with which to keep the
+            basic_block_info pointers stable.  Unthread the note now;
+            we'll put it back at the right place in create_basic_block.
+            Or not at all if we've already found a note in this block.  */
+         if (NOTE_INSN_BASIC_BLOCK_P (insn))
+           {
+             if (bb_note == NULL_RTX)
+               bb_note = insn;
+             else
+               next = delete_insn (insn);
+           }
+         break;
 
        case CODE_LABEL:
        case JUMP_INSN:
+       case CALL_INSN:
        case INSN:
        case BARRIER:
          break;
 
-       case CALL_INSN:
-         if (GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
-           {
-             /* Scan each of the alternatives for label refs.  */
-             lvl = find_label_refs (XEXP (PATTERN (insn), 0), lvl);
-             lvl = find_label_refs (XEXP (PATTERN (insn), 1), lvl);
-             lvl = find_label_refs (XEXP (PATTERN (insn), 2), lvl);
-             /* Record its tail recursion label, if any.  */
-             if (XEXP (PATTERN (insn), 3) != NULL_RTX)
-               trll = alloc_EXPR_LIST (0, XEXP (PATTERN (insn), 3), trll);
-           }
-         break;
-
        default:
-         abort ();
-       }
-
-      if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
-       {
-         rtx note;
-
-         /* Make a list of all labels referred to other than by jumps.
-
-            Make a special exception for labels followed by an ADDR*VEC,
-            as this would be a part of the tablejump setup code.
-
-            Make a special exception to registers loaded with label
-            values just before jump insns that use them.  */
-
-         for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
-           if (REG_NOTE_KIND (note) == REG_LABEL)
-             {
-               rtx lab = XEXP (note, 0), next;
-
-               if ((next = next_nonnote_insn (lab)) != NULL
-                        && GET_CODE (next) == JUMP_INSN
-                        && (GET_CODE (PATTERN (next)) == ADDR_VEC
-                            || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
-                 ;
-               else if (GET_CODE (lab) == NOTE)
-                 ;
-               else if (GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
-                        && find_reg_note (NEXT_INSN (insn), REG_LABEL, lab))
-                 ;
-               else
-                 lvl = alloc_EXPR_LIST (0, XEXP (note, 0), lvl);
-             }
+         gcc_unreachable ();
        }
     }
 
   if (head != NULL_RTX)
-    create_basic_block_structure (i++, head, end, bb_note);
+    create_basic_block_structure (head, end, bb_note, prev);
   else if (bb_note)
     delete_insn (bb_note);
 
-  if (i != n_basic_blocks)
-    abort ();
+  gcc_assert (last_basic_block == n_basic_blocks);
 
-  label_value_list = lvl;
-  tail_recursion_label_list = trll;
+  clear_aux_for_blocks ();
 }
 
 
 /* Find basic blocks of the current function.
-   F is the first insn of the function and NREGS the number of register
-   numbers in use.  */
+   F is the first insn of the function.  */
 
 void
-find_basic_blocks (f, nregs, file)
-     rtx f;
-     int nregs ATTRIBUTE_UNUSED;
-     FILE *file ATTRIBUTE_UNUSED;
+find_basic_blocks (rtx f)
 {
-  int max_uid;
-  timevar_push (TV_CFG);
+  basic_block bb;
 
-  basic_block_for_insn = 0;
+  timevar_push (TV_CFG);
 
   /* Flush out existing data.  */
   if (basic_block_info != NULL)
     {
-      int i;
-
       clear_edges ();
 
       /* Clear bb->aux on all extant basic blocks.  We'll use this as a
         tag for reuse during create_basic_block, just in case some pass
         copies around basic block notes improperly.  */
-      for (i = 0; i < n_basic_blocks; ++i)
-       BASIC_BLOCK (i)->aux = NULL;
+      FOR_EACH_BB (bb)
+       bb->aux = NULL;
 
-      VARRAY_FREE (basic_block_info);
+      basic_block_info = NULL;
     }
 
   n_basic_blocks = count_basic_blocks (f);
+  last_basic_block = NUM_FIXED_BLOCKS;
+  ENTRY_BLOCK_PTR->next_bb = EXIT_BLOCK_PTR;
+  EXIT_BLOCK_PTR->prev_bb = ENTRY_BLOCK_PTR;
+
 
   /* Size the basic block table.  The actual structures will be allocated
      by find_basic_blocks_1, since we want to keep the structure pointers
@@ -640,26 +543,21 @@ find_basic_blocks (f, nregs, file)
      instructions at all until close to the end of compilation when we
      actually lay them out.  */
 
-  VARRAY_BB_INIT (basic_block_info, n_basic_blocks, "basic_block_info");
+  basic_block_info = VEC_alloc (basic_block, gc, n_basic_blocks);
+  VEC_safe_grow_cleared (basic_block, gc, basic_block_info, n_basic_blocks);
+  SET_BASIC_BLOCK (ENTRY_BLOCK, ENTRY_BLOCK_PTR);
+  SET_BASIC_BLOCK (EXIT_BLOCK, EXIT_BLOCK_PTR);
 
   find_basic_blocks_1 (f);
 
-  /* Record the block to which an insn belongs.  */
-  /* ??? This should be done another way, by which (perhaps) a label is
-     tagged directly with the basic block that it starts.  It is used for
-     more than that currently, but IMO that is the only valid use.  */
-
-  max_uid = get_max_uid ();
-#ifdef AUTO_INC_DEC
-  /* Leave space for insns life_analysis makes in some cases for auto-inc.
-     These cases are rare, so we don't need too much space.  */
-  max_uid += max_uid / 10;
-#endif
+  profile_status = PROFILE_ABSENT;
 
-  compute_bb_for_insn (max_uid);
+  /* Tell make_edges to examine every block for out-going edges.  */
+  FOR_EACH_BB (bb)
+    SET_STATE (bb, BLOCK_NEW);
 
   /* Discover the edges of our cfg.  */
-  make_edges (label_value_list, 0, n_basic_blocks - 1, 0);
+  make_edges (ENTRY_BLOCK_PTR->next_bb, EXIT_BLOCK_PTR->prev_bb, 0);
 
   /* Do very simple cleanup now, for the benefit of code that runs between
      here and cleanup_cfg, e.g. thread_prologue_and_epilogue_insns.  */
@@ -671,28 +569,76 @@ find_basic_blocks (f, nregs, file)
   timevar_pop (TV_CFG);
 }
 \f
-/* State of basic block as seen by find_sub_basic_blocks.  */
-enum state {BLOCK_NEW = 0, BLOCK_ORIGINAL, BLOCK_TO_SPLIT};
+static void
+mark_tablejump_edge (rtx label)
+{
+  basic_block bb;
 
-#define STATE(BB) (enum state) ((size_t) (BB)->aux)
-#define SET_STATE(BB, STATE) ((BB)->aux = (void *) (size_t) (STATE))
+  gcc_assert (LABEL_P (label));
+  /* See comment in make_label_edge.  */
+  if (INSN_UID (label) == 0)
+    return;
+  bb = BLOCK_FOR_INSN (label);
+  SET_STATE (bb, FULL_STATE (bb) | BLOCK_USED_BY_TABLEJUMP);
+}
+
+static void
+purge_dead_tablejump_edges (basic_block bb, rtx table)
+{
+  rtx insn = BB_END (bb), tmp;
+  rtvec vec;
+  int j;
+  edge_iterator ei;
+  edge e;
+
+  if (GET_CODE (PATTERN (table)) == ADDR_VEC)
+    vec = XVEC (PATTERN (table), 0);
+  else
+    vec = XVEC (PATTERN (table), 1);
+
+  for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
+    mark_tablejump_edge (XEXP (RTVEC_ELT (vec, j), 0));
+
+  /* Some targets (eg, ARM) emit a conditional jump that also
+     contains the out-of-range target.  Scan for these and
+     add an edge if necessary.  */
+  if ((tmp = single_set (insn)) != NULL
+       && SET_DEST (tmp) == pc_rtx
+       && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
+       && GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF)
+    mark_tablejump_edge (XEXP (XEXP (SET_SRC (tmp), 2), 0));
+
+  for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
+    {
+      if (FULL_STATE (e->dest) & BLOCK_USED_BY_TABLEJUMP)
+       SET_STATE (e->dest, FULL_STATE (e->dest)
+                           & ~(size_t) BLOCK_USED_BY_TABLEJUMP);
+      else if (!(e->flags & (EDGE_ABNORMAL | EDGE_EH)))
+       {
+         remove_edge (e);
+         continue;
+       }
+      ei_next (&ei);
+    }
+}
 
 /* Scan basic block BB for possible BB boundaries inside the block
    and create new basic blocks in the progress.  */
 
 static void
-find_bb_boundaries (bb)
-     basic_block bb;
+find_bb_boundaries (basic_block bb)
 {
-  rtx insn = bb->head;
-  rtx end = bb->end;
+  basic_block orig_bb = bb;
+  rtx insn = BB_HEAD (bb);
+  rtx end = BB_END (bb), x;
+  rtx table;
   rtx flow_transfer_insn = NULL_RTX;
   edge fallthru = NULL;
 
-  if (insn == bb->end)
+  if (insn == BB_END (bb))
     return;
 
-  if (GET_CODE (insn) == CODE_LABEL)
+  if (LABEL_P (insn))
     insn = NEXT_INSN (insn);
 
   /* Scan insn chain and try to find new basic block boundaries.  */
@@ -705,12 +651,21 @@ find_bb_boundaries (bb)
        {
          fallthru = split_block (bb, PREV_INSN (insn));
          if (flow_transfer_insn)
-           bb->end = flow_transfer_insn;
+           {
+             BB_END (bb) = flow_transfer_insn;
+
+             /* Clean up the bb field for the insns between the blocks.  */
+             for (x = NEXT_INSN (flow_transfer_insn);
+                  x != BB_HEAD (fallthru->dest);
+                  x = NEXT_INSN (x))
+               if (!BARRIER_P (x))
+                 set_block_for_insn (x, NULL);
+           }
 
          bb = fallthru->dest;
          remove_edge (fallthru);
          flow_transfer_insn = NULL_RTX;
-         if (LABEL_ALTERNATE_NAME (insn))
+         if (LABEL_ALT_ENTRY_P (insn))
            make_edge (ENTRY_BLOCK_PTR, bb, 0);
        }
 
@@ -719,7 +674,15 @@ find_bb_boundaries (bb)
       if (flow_transfer_insn && inside_basic_block_p (insn))
        {
          fallthru = split_block (bb, PREV_INSN (insn));
-         bb->end = flow_transfer_insn;
+         BB_END (bb) = flow_transfer_insn;
+
+         /* Clean up the bb field for the insns between the blocks.  */
+         for (x = NEXT_INSN (flow_transfer_insn);
+              x != BB_HEAD (fallthru->dest);
+              x = NEXT_INSN (x))
+           if (!BARRIER_P (x))
+             set_block_for_insn (x, NULL);
+
          bb = fallthru->dest;
          remove_edge (fallthru);
          flow_transfer_insn = NULL_RTX;
@@ -736,146 +699,126 @@ find_bb_boundaries (bb)
      return and barrier, or possibly other sequence not behaving like
      ordinary jump, we need to take care and move basic block boundary.  */
   if (flow_transfer_insn)
-    bb->end = flow_transfer_insn;
+    {
+      BB_END (bb) = flow_transfer_insn;
+
+      /* Clean up the bb field for the insns that do not belong to BB.  */
+      x = flow_transfer_insn;
+      while (x != end)
+       {
+         x = NEXT_INSN (x);
+         if (!BARRIER_P (x))
+           set_block_for_insn (x, NULL);
+       }
+    }
 
   /* We've possibly replaced the conditional jump by conditional jump
      followed by cleanup at fallthru edge, so the outgoing edges may
      be dead.  */
   purge_dead_edges (bb);
+
+  /* purge_dead_edges doesn't handle tablejump's, but if we have split the
+     basic block, we might need to kill some edges.  */
+  if (bb != orig_bb && tablejump_p (BB_END (bb), NULL, &table))
+    purge_dead_tablejump_edges (bb, table);
 }
 
 /*  Assume that frequency of basic block B is known.  Compute frequencies
     and probabilities of outgoing edges.  */
 
 static void
-compute_outgoing_frequencies (b)
-     basic_block b;
+compute_outgoing_frequencies (basic_block b)
 {
   edge e, f;
+  edge_iterator ei;
 
-  if (b->succ && b->succ->succ_next && !b->succ->succ_next->succ_next)
+  if (EDGE_COUNT (b->succs) == 2)
     {
-      rtx note = find_reg_note (b->end, REG_BR_PROB, NULL);
+      rtx note = find_reg_note (BB_END (b), REG_BR_PROB, NULL);
       int probability;
 
-      if (!note)
-       return;
-
-      probability = INTVAL (XEXP (find_reg_note (b->end,
-                                                REG_BR_PROB, NULL),
-                                 0));
-      e = BRANCH_EDGE (b);
-      e->probability = probability;
-      e->count = ((b->count * probability + REG_BR_PROB_BASE / 2)
-                 / REG_BR_PROB_BASE);
-      f = FALLTHRU_EDGE (b);
-      f->probability = REG_BR_PROB_BASE - probability;
-      f->count = b->count - e->count;
+      if (note)
+       {
+         probability = INTVAL (XEXP (note, 0));
+         e = BRANCH_EDGE (b);
+         e->probability = probability;
+         e->count = ((b->count * probability + REG_BR_PROB_BASE / 2)
+                     / REG_BR_PROB_BASE);
+         f = FALLTHRU_EDGE (b);
+         f->probability = REG_BR_PROB_BASE - probability;
+         f->count = b->count - e->count;
+         return;
+       }
     }
 
-  if (b->succ && !b->succ->succ_next)
+  if (single_succ_p (b))
     {
-      e = b->succ;
+      e = single_succ_edge (b);
       e->probability = REG_BR_PROB_BASE;
       e->count = b->count;
+      return;
     }
+  guess_outgoing_edge_probabilities (b);
+  if (b->count)
+    FOR_EACH_EDGE (e, ei, b->succs)
+      e->count = ((b->count * e->probability + REG_BR_PROB_BASE / 2)
+                 / REG_BR_PROB_BASE);
 }
 
-/* Assume that someone emitted code with control flow instructions to the
-   basic block.  Update the data structure.  */
+/* Assume that some pass has inserted labels or control flow
+   instructions within a basic block.  Split basic blocks as needed
+   and create edges.  */
 
 void
-find_many_sub_basic_blocks (blocks)
-     sbitmap blocks;
+find_many_sub_basic_blocks (sbitmap blocks)
 {
-  int i;
-  int min, max;
+  basic_block bb, min, max;
 
-  for (i = 0; i < n_basic_blocks; i++)
-    SET_STATE (BASIC_BLOCK (i),
-              TEST_BIT (blocks, i) ? BLOCK_TO_SPLIT : BLOCK_ORIGINAL);
+  FOR_EACH_BB (bb)
+    SET_STATE (bb,
+              TEST_BIT (blocks, bb->index) ? BLOCK_TO_SPLIT : BLOCK_ORIGINAL);
 
-  for (i = 0; i < n_basic_blocks; i++)
-    if (STATE (BASIC_BLOCK (i)) == BLOCK_TO_SPLIT)
-      find_bb_boundaries (BASIC_BLOCK (i));
+  FOR_EACH_BB (bb)
+    if (STATE (bb) == BLOCK_TO_SPLIT)
+      find_bb_boundaries (bb);
 
-  for (i = 0; i < n_basic_blocks; i++)
-    if (STATE (BASIC_BLOCK (i)) != BLOCK_ORIGINAL)
+  FOR_EACH_BB (bb)
+    if (STATE (bb) != BLOCK_ORIGINAL)
       break;
 
-  min = max = i;
-  for (; i < n_basic_blocks; i++)
-    if (STATE (BASIC_BLOCK (i)) != BLOCK_ORIGINAL)
-      max = i;
+  min = max = bb;
+  for (; bb != EXIT_BLOCK_PTR; bb = bb->next_bb)
+    if (STATE (bb) != BLOCK_ORIGINAL)
+      max = bb;
 
   /* Now re-scan and wire in all edges.  This expect simple (conditional)
      jumps at the end of each new basic blocks.  */
-  make_edges (NULL, min, max, 1);
+  make_edges (min, max, 1);
 
   /* Update branch probabilities.  Expect only (un)conditional jumps
      to be created with only the forward edges.  */
-  for (i = min; i <= max; i++)
-    {
-      edge e;
-      basic_block b = BASIC_BLOCK (i);
-
-      if (STATE (b) == BLOCK_ORIGINAL)
-       continue;
-      if (STATE (b) == BLOCK_NEW)
-       {
-         b->count = 0;
-         b->frequency = 0;
-         for (e = b->pred; e; e=e->pred_next)
-           {
-             b->count += e->count;
-             b->frequency += EDGE_FREQUENCY (e);
-           }
-       }
-
-      compute_outgoing_frequencies (b);
-    }
-
-  for (i = 0; i < n_basic_blocks; i++)
-    SET_STATE (BASIC_BLOCK (i), 0);
-}
-
-/* Like above but for single basic block only.  */
-
-void
-find_sub_basic_blocks (bb)
-    basic_block bb;
-{
-  int i;
-  int min, max;
-  basic_block next = (bb->index == n_basic_blocks - 1
-                     ? NULL : BASIC_BLOCK (bb->index + 1));
-
-  min = bb->index;
-  find_bb_boundaries (bb);
-  max = (next ? next->index : n_basic_blocks) - 1;
-
-  /* Now re-scan and wire in all edges.  This expect simple (conditional)
-     jumps at the end of each new basic blocks.  */
-  make_edges (NULL, min, max, 1);
+  if (profile_status != PROFILE_ABSENT)
+    FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
+      {
+       edge e;
+       edge_iterator ei;
 
-  /* Update branch probabilities.  Expect only (un)conditional jumps
-     to be created with only the forward edges.  */
-  for (i = min; i <= max; i++)
-    {
-      edge e;
-      basic_block b = BASIC_BLOCK (i);
+       if (STATE (bb) == BLOCK_ORIGINAL)
+         continue;
+       if (STATE (bb) == BLOCK_NEW)
+         {
+           bb->count = 0;
+           bb->frequency = 0;
+           FOR_EACH_EDGE (e, ei, bb->preds)
+             {
+               bb->count += e->count;
+               bb->frequency += EDGE_FREQUENCY (e);
+             }
+         }
 
-      if (i != min)
-       {
-         b->count = 0;
-         b->frequency = 0;
-         for (e = b->pred; e; e=e->pred_next)
-           {
-             b->count += e->count;
-             b->frequency += EDGE_FREQUENCY (e);
-           }
-       }
+       compute_outgoing_frequencies (bb);
+      }
 
-      compute_outgoing_frequencies (b);
-    }
+  FOR_EACH_BB (bb)
+    SET_STATE (bb, 0);
 }