OSDN Git Service

2006-01-18 Andrew Pinski <pinskia@physics.uc.edu>
[pf3gnuchains/gcc-fork.git] / gcc / cfgrtl.c
index ae073c4..7652472 100644 (file)
@@ -1,6 +1,6 @@
 /* Control flow graph manipulation code for GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -16,8 +16,8 @@ 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.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 /* This file contains low level functions to manipulate the CFG and analyze it
    that are aware of the RTL intermediate language.
@@ -56,19 +56,16 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "insn-config.h"
 #include "cfglayout.h"
 #include "expr.h"
-
-
-/* The labels mentioned in non-jump rtl.  Valid during find_basic_blocks.  */
-/* ??? Should probably be using LABEL_NUSES instead.  It would take a
-   bit of surgery to be able to use or co-opt the routines in jump.  */
-rtx label_value_list;
+#include "target.h"
+#include "cfgloop.h"
+#include "ggc.h"
+#include "tree-pass.h"
 
 static int can_delete_note_p (rtx);
 static int can_delete_label_p (rtx);
 static void commit_one_edge_insertion (edge, int);
 static rtx last_loop_beg_note (rtx);
 static bool back_edge_of_syntactic_loop_p (basic_block, basic_block);
-basic_block force_nonfallthru_and_redirect (edge, basic_block);
 static basic_block rtl_split_edge (edge);
 static bool rtl_move_block_after (basic_block, basic_block);
 static int rtl_verify_flow_info (void);
@@ -92,9 +89,7 @@ static int
 can_delete_note_p (rtx note)
 {
   return (NOTE_LINE_NUMBER (note) == NOTE_INSN_DELETED
-         || NOTE_LINE_NUMBER (note) == NOTE_INSN_BASIC_BLOCK
-         || NOTE_LINE_NUMBER (note) == NOTE_INSN_UNLIKELY_EXECUTED_CODE
-         || NOTE_LINE_NUMBER (note) == NOTE_INSN_PREDICTION);
+         || NOTE_LINE_NUMBER (note) == NOTE_INSN_BASIC_BLOCK);
 }
 
 /* True if a given label can be deleted.  */
@@ -105,8 +100,7 @@ can_delete_label_p (rtx label)
   return (!LABEL_PRESERVE_P (label)
          /* User declared labels must be preserved.  */
          && LABEL_NAME (label) == 0
-         && !in_expr_list_p (forced_labels, label)
-         && !in_expr_list_p (label_value_list, label));
+         && !in_expr_list_p (forced_labels, label));
 }
 
 /* Delete INSN by patching it out.  Return the next insn.  */
@@ -118,7 +112,7 @@ delete_insn (rtx insn)
   rtx note;
   bool really_delete = true;
 
-  if (GET_CODE (insn) == CODE_LABEL)
+  if (LABEL_P (insn))
     {
       /* Some labels can't be directly removed from the INSN chain, as they
          might be references via variables, constant pool etc.
@@ -139,31 +133,30 @@ delete_insn (rtx insn)
   if (really_delete)
     {
       /* If this insn has already been deleted, something is very wrong.  */
-      if (INSN_DELETED_P (insn))
-       abort ();
+      gcc_assert (!INSN_DELETED_P (insn));
       remove_insn (insn);
       INSN_DELETED_P (insn) = 1;
     }
 
   /* If deleting a jump, decrement the use count of the label.  Deleting
      the label itself should happen in the normal course of block merging.  */
-  if (GET_CODE (insn) == JUMP_INSN
+  if (JUMP_P (insn)
       && JUMP_LABEL (insn)
-      && GET_CODE (JUMP_LABEL (insn)) == CODE_LABEL)
+      && LABEL_P (JUMP_LABEL (insn)))
     LABEL_NUSES (JUMP_LABEL (insn))--;
 
   /* Also if deleting an insn that references a label.  */
   else
     {
       while ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)) != NULL_RTX
-            && GET_CODE (XEXP (note, 0)) == CODE_LABEL)
+            && LABEL_P (XEXP (note, 0)))
        {
          LABEL_NUSES (XEXP (note, 0))--;
          remove_note (insn, note);
        }
     }
 
-  if (GET_CODE (insn) == JUMP_INSN
+  if (JUMP_P (insn)
       && (GET_CODE (PATTERN (insn)) == ADDR_VEC
          || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
     {
@@ -179,7 +172,7 @@ delete_insn (rtx insn)
          /* When deleting code in bulk (e.g. removing many unreachable
             blocks) we can delete a label that's a target of the vector
             before deleting the vector itself.  */
-         if (GET_CODE (label) != NOTE)
+         if (!NOTE_P (label))
            LABEL_NUSES (label)--;
        }
     }
@@ -218,7 +211,7 @@ delete_insn_chain (rtx start, rtx finish)
   while (1)
     {
       next = NEXT_INSN (start);
-      if (GET_CODE (start) == NOTE && !can_delete_note_p (start))
+      if (NOTE_P (start) && !can_delete_note_p (start))
        ;
       else
        next = delete_insn (start);
@@ -265,7 +258,7 @@ create_basic_block_structure (rtx head, rtx end, rtx bb_note, basic_block after)
 
       rtx after;
 
-      if (GET_CODE (head) == CODE_LABEL)
+      if (LABEL_P (head))
        after = head;
       else
        {
@@ -282,10 +275,11 @@ create_basic_block_structure (rtx head, rtx end, rtx bb_note, basic_block after)
 
       bb = alloc_block ();
 
+      init_rtl_bb_info (bb);
       if (!head && !end)
        head = end = bb_note
          = emit_note_after (NOTE_INSN_BASIC_BLOCK, get_last_insn ());
-      else if (GET_CODE (head) == CODE_LABEL && end)
+      else if (LABEL_P (head) && end)
        {
          bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK, head);
          if (head == end)
@@ -309,11 +303,11 @@ create_basic_block_structure (rtx head, rtx end, rtx bb_note, basic_block after)
   BB_HEAD (bb) = head;
   BB_END (bb) = end;
   bb->index = last_basic_block++;
-  bb->flags = BB_NEW;
+  bb->flags = BB_NEW | BB_RTL;
   link_block (bb, after);
-  BASIC_BLOCK (bb->index) = bb;
+  SET_BASIC_BLOCK (bb->index, bb);
   update_bb_for_insn (bb);
-  bb->partition = UNPARTITIONED;
+  BB_SET_PARTITION (bb, BB_UNPARTITIONED);
 
   /* Tag the block so that we know it has been used when considering
      other basic block notes.  */
@@ -334,10 +328,14 @@ rtl_create_basic_block (void *headp, void *endp, basic_block after)
   basic_block bb;
 
   /* Grow the basic block array if needed.  */
-  if ((size_t) last_basic_block >= VARRAY_SIZE (basic_block_info))
+  if ((size_t) last_basic_block >= VEC_length (basic_block, basic_block_info))
     {
+      size_t old_size = VEC_length (basic_block, basic_block_info);
       size_t new_size = last_basic_block + (last_basic_block + 3) / 4;
-      VARRAY_GROW (basic_block_info, new_size);
+      basic_block *p;
+      VEC_safe_grow (basic_block, gc, basic_block_info, new_size);
+      p = VEC_address (basic_block, basic_block_info);
+      memset (&p[old_size], 0, sizeof (basic_block) * (new_size - old_size));
     }
 
   n_basic_blocks++;
@@ -352,7 +350,6 @@ cfg_layout_create_basic_block (void *head, void *end, basic_block after)
 {
   basic_block newbb = rtl_create_basic_block (head, end, after);
 
-  initialize_bb_rbi (newbb);
   return newbb;
 }
 \f
@@ -370,27 +367,10 @@ rtl_delete_block (basic_block b)
   rtx insn, end, tmp;
 
   /* If the head of this block is a CODE_LABEL, then it might be the
-     label for an exception handler which can't be reached.
-
-     We need to remove the label from the exception_handler_label list
-     and remove the associated NOTE_INSN_EH_REGION_BEG and
-     NOTE_INSN_EH_REGION_END notes.  */
-
-  /* Get rid of all NOTE_INSN_PREDICTIONs and NOTE_INSN_LOOP_CONTs
-     hanging before the block.  */
-
-  for (insn = PREV_INSN (BB_HEAD (b)); insn; insn = PREV_INSN (insn))
-    {
-      if (GET_CODE (insn) != NOTE)
-       break;
-      if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PREDICTION
-         || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_CONT)
-       NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-    }
-
+     label for an exception handler which can't be reached.  We need
+     to remove the label from the exception_handler_label list.  */
   insn = BB_HEAD (b);
-
-  if (GET_CODE (insn) == CODE_LABEL)
+  if (LABEL_P (insn))
     maybe_remove_eh_handler (insn);
 
   /* Include any jump table following the basic block.  */
@@ -398,10 +378,13 @@ rtl_delete_block (basic_block b)
   if (tablejump_p (end, NULL, &tmp))
     end = tmp;
 
-  /* Include any barrier that may follow the basic block.  */
+  /* Include any barriers that may follow the basic block.  */
   tmp = next_nonnote_insn (end);
-  if (tmp && GET_CODE (tmp) == BARRIER)
-    end = tmp;
+  while (tmp && BARRIER_P (tmp))
+    {
+      end = tmp;
+      tmp = next_nonnote_insn (end);
+    }
 
   /* Selectively delete the entire chain.  */
   BB_HEAD (b) = NULL;
@@ -436,15 +419,33 @@ free_bb_for_insn (void)
 {
   rtx insn;
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
-    if (GET_CODE (insn) != BARRIER)
+    if (!BARRIER_P (insn))
       BLOCK_FOR_INSN (insn) = NULL;
 }
 
+struct tree_opt_pass pass_free_cfg =
+{
+  NULL,                                 /* name */
+  NULL,                                 /* gate */
+  free_bb_for_insn,                     /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  0,                                    /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  PROP_cfg,                             /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  0,                                    /* todo_flags_finish */
+  0                                     /* letter */
+};
+
 /* Return RTX to emit after when we want to emit code on the entry of function.  */
 rtx
 entry_of_function (void)
 {
-  return (n_basic_blocks ? BB_HEAD (ENTRY_BLOCK_PTR->next_bb) : get_insns ());
+  return (n_basic_blocks > NUM_FIXED_BLOCKS ? 
+         BB_HEAD (ENTRY_BLOCK_PTR->next_bb) : get_insns ());
 }
 
 /* Update insns block within BB.  */
@@ -456,7 +457,7 @@ update_bb_for_insn (basic_block bb)
 
   for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
     {
-      if (GET_CODE (insn) != BARRIER)
+      if (!BARRIER_P (insn))
        set_block_for_insn (insn, bb);
       if (insn == BB_END (bb))
        break;
@@ -472,6 +473,7 @@ rtl_split_block (basic_block bb, void *insnp)
   basic_block new_bb;
   rtx insn = insnp;
   edge e;
+  edge_iterator ei;
 
   if (!insn)
     {
@@ -491,29 +493,30 @@ rtl_split_block (basic_block bb, void *insnp)
 
   /* Create the new basic block.  */
   new_bb = create_basic_block (NEXT_INSN (insn), BB_END (bb), bb);
+  BB_COPY_PARTITION (new_bb, bb);
   BB_END (bb) = insn;
 
   /* Redirect the outgoing edges.  */
-  new_bb->succ = bb->succ;
-  bb->succ = NULL;
-  for (e = new_bb->succ; e; e = e->succ_next)
+  new_bb->succs = bb->succs;
+  bb->succs = NULL;
+  FOR_EACH_EDGE (e, ei, new_bb->succs)
     e->src = new_bb;
 
-  if (bb->global_live_at_start)
+  if (bb->il.rtl->global_live_at_start)
     {
-      new_bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
-      new_bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
-      COPY_REG_SET (new_bb->global_live_at_end, bb->global_live_at_end);
+      new_bb->il.rtl->global_live_at_start = ALLOC_REG_SET (&reg_obstack);
+      new_bb->il.rtl->global_live_at_end = ALLOC_REG_SET (&reg_obstack);
+      COPY_REG_SET (new_bb->il.rtl->global_live_at_end, bb->il.rtl->global_live_at_end);
 
       /* We now have to calculate which registers are live at the end
         of the split basic block and at the start of the new basic
         block.  Start with those registers that are known to be live
         at the end of the original basic block and get
         propagate_block to determine which registers are live.  */
-      COPY_REG_SET (new_bb->global_live_at_start, bb->global_live_at_end);
-      propagate_block (new_bb, new_bb->global_live_at_start, NULL, NULL, 0);
-      COPY_REG_SET (bb->global_live_at_end,
-                   new_bb->global_live_at_start);
+      COPY_REG_SET (new_bb->il.rtl->global_live_at_start, bb->il.rtl->global_live_at_end);
+      propagate_block (new_bb, new_bb->il.rtl->global_live_at_start, NULL, NULL, 0);
+      COPY_REG_SET (bb->il.rtl->global_live_at_end,
+                   new_bb->il.rtl->global_live_at_start);
 #ifdef HAVE_conditional_execution
       /* In the presence of conditional execution we are not able to update
         liveness precisely.  */
@@ -539,8 +542,12 @@ rtl_merge_blocks (basic_block a, basic_block b)
   int b_empty = 0;
 
   /* If there was a CODE_LABEL beginning B, delete it.  */
-  if (GET_CODE (b_head) == CODE_LABEL)
+  if (LABEL_P (b_head))
     {
+      /* This might have been an EH label that no longer has incoming
+        EH edges.  Update data structures to match.  */
+      maybe_remove_eh_handler (b_head);
       /* Detect basic blocks with nothing but a label.  This can happen
         in particular at the end of a function.  */
       if (b_head == b_end)
@@ -564,12 +571,12 @@ rtl_merge_blocks (basic_block a, basic_block b)
     }
 
   /* If there was a jump out of A, delete it.  */
-  if (GET_CODE (a_end) == JUMP_INSN)
+  if (JUMP_P (a_end))
     {
       rtx prev;
 
       for (prev = PREV_INSN (a_end); ; prev = PREV_INSN (prev))
-       if (GET_CODE (prev) != NOTE
+       if (!NOTE_P (prev)
            || NOTE_LINE_NUMBER (prev) == NOTE_INSN_BASIC_BLOCK
            || prev == BB_HEAD (a))
          break;
@@ -592,7 +599,7 @@ rtl_merge_blocks (basic_block a, basic_block b)
 
       a_end = PREV_INSN (del_first);
     }
-  else if (GET_CODE (NEXT_INSN (a_end)) == BARRIER)
+  else if (BARRIER_P (NEXT_INSN (a_end)))
     del_first = NEXT_INSN (a_end);
 
   /* Delete everything marked above as well as crap that might be
@@ -614,35 +621,38 @@ rtl_merge_blocks (basic_block a, basic_block b)
     }
 
   BB_END (a) = a_end;
+  a->il.rtl->global_live_at_end = b->il.rtl->global_live_at_end;
 }
 
 /* Return true when block A and B can be merged.  */
 static bool
 rtl_can_merge_blocks (basic_block a,basic_block b)
 {
-  bool partitions_ok = true;
-
   /* If we are partitioning hot/cold basic blocks, we don't want to
      mess up unconditional or indirect jumps that cross between hot
-     and cold sections.  */
-  
-  if (flag_reorder_blocks_and_partition
-      && (find_reg_note (BB_END (a), REG_CROSSING_JUMP, NULL_RTX)
-         || find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX)
-         || a->partition != b->partition))
-    partitions_ok = false;
+     and cold sections.
+
+     Basic block partitioning may result in some jumps that appear to
+     be optimizable (or blocks that appear to be mergeable), but which really 
+     must be left untouched (they are required to make it safely across 
+     partition boundaries).  See  the comments at the top of 
+     bb-reorder.c:partition_hot_cold_basic_blocks for complete details.  */
+
+  if (BB_PARTITION (a) != BB_PARTITION (b))
+    return false;
 
   /* There must be exactly one edge in between the blocks.  */
-  return (a->succ && !a->succ->succ_next && a->succ->dest == b
-         && !b->pred->pred_next && a != b
+  return (single_succ_p (a)
+         && single_succ (a) == b
+         && single_pred_p (b)
+         && a != b
          /* Must be simple edge.  */
-         && !(a->succ->flags & EDGE_COMPLEX)
-         && partitions_ok
+         && !(single_succ_edge (a)->flags & EDGE_COMPLEX)
          && a->next_bb == b
          && a != ENTRY_BLOCK_PTR && b != EXIT_BLOCK_PTR
          /* If the jump insn has side effects,
             we can't kill the edge.  */
-         && (GET_CODE (BB_END (a)) != JUMP_INSN
+         && (!JUMP_P (BB_END (a))
              || (reload_completed
                  ? simplejump_p (BB_END (a)) : onlyjump_p (BB_END (a)))));
 }
@@ -656,7 +666,7 @@ block_label (basic_block block)
   if (block == EXIT_BLOCK_PTR)
     return NULL_RTX;
 
-  if (GET_CODE (BB_HEAD (block)) != CODE_LABEL)
+  if (!LABEL_P (BB_HEAD (block)))
     {
       BB_HEAD (block) = emit_label_before (gen_label_rtx (), BB_HEAD (block));
     }
@@ -674,25 +684,34 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
 {
   basic_block src = e->src;
   rtx insn = BB_END (src), kill_from;
-  edge tmp;
   rtx set;
   int fallthru = 0;
 
-
   /* If we are partitioning hot/cold basic blocks, we don't want to
      mess up unconditional or indirect jumps that cross between hot
-     and cold sections.  */
+     and cold sections.
+
+     Basic block partitioning may result in some jumps that appear to
+     be optimizable (or blocks that appear to be mergeable), but which really 
+     must be left untouched (they are required to make it safely across 
+     partition boundaries).  See  the comments at the top of 
+     bb-reorder.c:partition_hot_cold_basic_blocks for complete details.  */
   
-  if (flag_reorder_blocks_and_partition
-      && find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX))
+  if (find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)
+      || BB_PARTITION (src) != BB_PARTITION (target))
     return NULL;
 
-  /* Verify that all targets will be TARGET.  */
-  for (tmp = src->succ; tmp; tmp = tmp->succ_next)
-    if (tmp->dest != target && tmp != e)
-      break;
+  /* We can replace or remove a complex jump only when we have exactly
+     two edges.  Also, if we have exactly one outgoing edge, we can
+     redirect that.  */
+  if (EDGE_COUNT (src->succs) >= 3
+      /* Verify that all targets will be TARGET.  Specifically, the
+        edge that is not E must also go to TARGET.  */
+      || (EDGE_COUNT (src->succs) == 2
+         && EDGE_SUCC (src, EDGE_SUCC (src, 0) == e)->dest != target))
+    return NULL;
 
-  if (tmp || !onlyjump_p (insn))
+  if (!onlyjump_p (insn))
     return NULL;
   if ((!optimize || reload_completed) && tablejump_p (insn, NULL, NULL))
     return NULL;
@@ -720,23 +739,23 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
       /* Selectively unlink whole insn chain.  */
       if (in_cfglayout)
        {
-         rtx insn = src->rbi->footer;
+         rtx insn = src->il.rtl->footer;
 
           delete_insn_chain (kill_from, BB_END (src));
 
          /* Remove barriers but keep jumptables.  */
          while (insn)
            {
-             if (GET_CODE (insn) == BARRIER)
+             if (BARRIER_P (insn))
                {
                  if (PREV_INSN (insn))
                    NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
                  else
-                   src->rbi->footer = NEXT_INSN (insn);
+                   src->il.rtl->footer = NEXT_INSN (insn);
                  if (NEXT_INSN (insn))
                    PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
                }
-             if (GET_CODE (insn) == CODE_LABEL)
+             if (LABEL_P (insn))
                break;
              insn = NEXT_INSN (insn);
            }
@@ -755,9 +774,8 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
                 INSN_UID (insn), e->dest->index, target->index);
       if (!redirect_jump (insn, block_label (target), 0))
        {
-         if (target == EXIT_BLOCK_PTR)
-           return NULL;
-         abort ();
+         gcc_assert (target == EXIT_BLOCK_PTR);
+         return NULL;
        }
     }
 
@@ -771,7 +789,7 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
       rtx target_label = block_label (target);
       rtx barrier, label, table;
 
-      emit_jump_insn_after (gen_jump (target_label), insn);
+      emit_jump_insn_after_noloc (gen_jump (target_label), insn);
       JUMP_LABEL (BB_END (src)) = target_label;
       LABEL_NUSES (target_label)++;
       if (dump_file)
@@ -788,7 +806,7 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
        delete_insn_chain (label, table);
 
       barrier = next_nonnote_insn (BB_END (src));
-      if (!barrier || GET_CODE (barrier) != BARRIER)
+      if (!barrier || !BARRIER_P (barrier))
        emit_barrier_after (BB_END (src));
       else
        {
@@ -817,9 +835,11 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
     }
 
   /* Keep only one edge out and set proper flags.  */
-  while (src->succ->succ_next)
-    remove_edge (src->succ);
-  e = src->succ;
+  if (!single_succ_p (src))
+    remove_edge (e);
+  gcc_assert (single_succ_p (src));
+
+  e = single_succ_edge (src);
   if (fallthru)
     e->flags = EDGE_FALLTHRU;
   else
@@ -830,7 +850,7 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
 
   /* We don't want a block to end on a line-number note since that has
      the potential of changing the code between -g and not -g.  */
-  while (GET_CODE (BB_END (e->src)) == NOTE
+  while (NOTE_P (BB_END (e->src))
         && NOTE_LINE_NUMBER (BB_END (e->src)) >= 0)
     delete_insn (BB_END (e->src));
 
@@ -853,7 +873,7 @@ last_loop_beg_note (rtx insn)
 {
   rtx last = insn;
 
-  for (insn = NEXT_INSN (insn); insn && GET_CODE (insn) == NOTE
+  for (insn = NEXT_INSN (insn); insn && NOTE_P (insn)
        && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK;
        insn = NEXT_INSN (insn))
     if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
@@ -875,7 +895,7 @@ redirect_branch_edge (edge e, basic_block target)
   /* We can only redirect non-fallthru edges of jump insn.  */
   if (e->flags & EDGE_FALLTHRU)
     return NULL;
-  else if (GET_CODE (insn) != JUMP_INSN)
+  else if (!JUMP_P (insn))
     return NULL;
 
   /* Recognize a tablejump and adjust all matching cases.  */
@@ -907,7 +927,7 @@ redirect_branch_edge (edge e, basic_block target)
          && GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF
          && XEXP (XEXP (SET_SRC (tmp), 2), 0) == old_label)
        {
-         XEXP (SET_SRC (tmp), 2) = gen_rtx_LABEL_REF (VOIDmode,
+         XEXP (SET_SRC (tmp), 2) = gen_rtx_LABEL_REF (Pmode,
                                                       new_label);
          --LABEL_NUSES (old_label);
          ++LABEL_NUSES (new_label);
@@ -924,17 +944,15 @@ redirect_branch_edge (edge e, basic_block target)
        return NULL;
 
       /* If the insn doesn't go where we think, we're confused.  */
-      if (JUMP_LABEL (insn) != old_label)
-       abort ();
+      gcc_assert (JUMP_LABEL (insn) == old_label);
 
       /* If the substitution doesn't succeed, die.  This can happen
         if the back end emitted unrecognizable instructions or if
         target is exit block on some arches.  */
       if (!redirect_jump (insn, block_label (target), 0))
        {
-         if (target == EXIT_BLOCK_PTR)
-           return NULL;
-         abort ();
+         gcc_assert (target == EXIT_BLOCK_PTR);
+         return NULL;
        }
     }
 
@@ -987,7 +1005,7 @@ rtl_redirect_edge_and_branch (edge e, basic_block target)
 /* Like force_nonfallthru below, but additionally performs redirection
    Used by redirect_edge_and_branch_force.  */
 
-basic_block
+static basic_block
 force_nonfallthru_and_redirect (edge e, basic_block target)
 {
   basic_block jump_block, new_bb = NULL, src = e->src;
@@ -1000,16 +1018,15 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
      by creating a basic block afterwards to redirect fallthru edge.  */
   if (e->src != ENTRY_BLOCK_PTR && e->dest != EXIT_BLOCK_PTR
       && any_condjump_p (BB_END (e->src))
-      /* When called from cfglayout, fallthru edges do not
-         necessarily go to the next block.  */
-      && e->src->next_bb == e->dest
       && JUMP_LABEL (BB_END (e->src)) == BB_HEAD (e->dest))
     {
       rtx note;
       edge b = unchecked_make_edge (e->src, target, 0);
+      bool redirected;
 
-      if (!redirect_jump (BB_END (e->src), block_label (target), 0))
-       abort ();
+      redirected = redirect_jump (BB_END (e->src), block_label (target), 0);
+      gcc_assert (redirected);
+      
       note = find_reg_note (BB_END (e->src), REG_BR_PROB, NULL_RTX);
       if (note)
        {
@@ -1033,35 +1050,47 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
         We can't redirect abnormal edge, but we still can split the fallthru
         one and create separate abnormal edge to original destination.
         This allows bb-reorder to make such edge non-fallthru.  */
-      if (e->dest != target)
-       abort ();
+      gcc_assert (e->dest == target);
       abnormal_edge_flags = e->flags & ~(EDGE_FALLTHRU | EDGE_CAN_FALLTHRU);
       e->flags &= EDGE_FALLTHRU | EDGE_CAN_FALLTHRU;
     }
-  else if (!(e->flags & EDGE_FALLTHRU))
-    abort ();
-  else if (e->src == ENTRY_BLOCK_PTR)
+  else
     {
-      /* We can't redirect the entry block.  Create an empty block at the
-         start of the function which we use to add the new jump.  */
-      edge *pe1;
-      basic_block bb = create_basic_block (BB_HEAD (e->dest), NULL, ENTRY_BLOCK_PTR);
-
-      /* Change the existing edge's source to be the new block, and add
-        a new edge from the entry block to the new block.  */
-      e->src = bb;
-      for (pe1 = &ENTRY_BLOCK_PTR->succ; *pe1; pe1 = &(*pe1)->succ_next)
-       if (*pe1 == e)
-         {
-           *pe1 = e->succ_next;
-           break;
-         }
-      e->succ_next = 0;
-      bb->succ = e;
-      make_single_succ_edge (ENTRY_BLOCK_PTR, bb, EDGE_FALLTHRU);
+      gcc_assert (e->flags & EDGE_FALLTHRU);
+      if (e->src == ENTRY_BLOCK_PTR)
+       {
+         /* We can't redirect the entry block.  Create an empty block
+            at the start of the function which we use to add the new
+            jump.  */
+         edge tmp;
+         edge_iterator ei;
+         bool found = false;
+         
+         basic_block bb = create_basic_block (BB_HEAD (e->dest), NULL, ENTRY_BLOCK_PTR);
+         
+         /* Change the existing edge's source to be the new block, and add
+            a new edge from the entry block to the new block.  */
+         e->src = bb;
+         for (ei = ei_start (ENTRY_BLOCK_PTR->succs); (tmp = ei_safe_edge (ei)); )
+           {
+             if (tmp == e)
+               {
+                 VEC_unordered_remove (edge, ENTRY_BLOCK_PTR->succs, ei.index);
+                 found = true;
+                 break;
+               }
+             else
+               ei_next (&ei);
+           }
+         
+         gcc_assert (found);
+         
+         VEC_safe_push (edge, gc, bb->succs, e);
+         make_single_succ_edge (ENTRY_BLOCK_PTR, bb, EDGE_FALLTHRU);
+       }
     }
 
-  if (e->src->succ->succ_next || abnormal_edge_flags)
+  if (EDGE_COUNT (e->src->succs) >= 2 || abnormal_edge_flags)
     {
       /* Create the new structures.  */
 
@@ -1080,45 +1109,30 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
       jump_block->frequency = EDGE_FREQUENCY (e);
       jump_block->loop_depth = target->loop_depth;
 
-      if (target->global_live_at_start)
+      if (target->il.rtl->global_live_at_start)
        {
-         jump_block->global_live_at_start
-           = OBSTACK_ALLOC_REG_SET (&flow_obstack);
-         jump_block->global_live_at_end
-           = OBSTACK_ALLOC_REG_SET (&flow_obstack);
-         COPY_REG_SET (jump_block->global_live_at_start,
-                       target->global_live_at_start);
-         COPY_REG_SET (jump_block->global_live_at_end,
-                       target->global_live_at_start);
+         jump_block->il.rtl->global_live_at_start = ALLOC_REG_SET (&reg_obstack);
+         jump_block->il.rtl->global_live_at_end = ALLOC_REG_SET (&reg_obstack);
+         COPY_REG_SET (jump_block->il.rtl->global_live_at_start,
+                       target->il.rtl->global_live_at_start);
+         COPY_REG_SET (jump_block->il.rtl->global_live_at_end,
+                       target->il.rtl->global_live_at_start);
        }
 
       /* Make sure new block ends up in correct hot/cold section.  */
 
-      jump_block->partition = e->src->partition;
-      if (flag_reorder_blocks_and_partition)
-       {
-         if (e->src->partition == COLD_PARTITION)
-           {
-             rtx bb_note, new_note;
-             for (bb_note = BB_HEAD (jump_block); 
-                  bb_note && bb_note != NEXT_INSN (BB_END (jump_block));
-                  bb_note = NEXT_INSN (bb_note))
-               if (GET_CODE (bb_note) == NOTE
-                   && NOTE_LINE_NUMBER (bb_note) == NOTE_INSN_BASIC_BLOCK)
-                 break;
-             new_note = emit_note_after (NOTE_INSN_UNLIKELY_EXECUTED_CODE,
-                                         bb_note);
-             NOTE_BASIC_BLOCK (new_note) = jump_block; 
-             jump_block->partition = COLD_PARTITION;
-           }
-         if (GET_CODE (BB_END (jump_block)) == JUMP_INSN
-             && !any_condjump_p (BB_END (jump_block))
-             && jump_block->succ->crossing_edge )
-           REG_NOTES (BB_END (jump_block)) = gen_rtx_EXPR_LIST 
-             (REG_CROSSING_JUMP, NULL_RTX, 
-              REG_NOTES (BB_END (jump_block)));
-       }
-
+      BB_COPY_PARTITION (jump_block, e->src);
+      if (flag_reorder_blocks_and_partition
+         && targetm.have_named_sections
+         && JUMP_P (BB_END (jump_block))
+         && !any_condjump_p (BB_END (jump_block))
+         && (EDGE_SUCC (jump_block, 0)->flags & EDGE_CROSSING))
+       REG_NOTES (BB_END (jump_block)) = gen_rtx_EXPR_LIST (REG_CROSSING_JUMP,
+                                                            NULL_RTX,
+                                                            REG_NOTES
+                                                            (BB_END
+                                                              (jump_block)));
+      
       /* Wire edge in.  */
       new_edge = make_edge (e->src, jump_block, EDGE_FALLTHRU);
       new_edge->probability = e->probability;
@@ -1137,15 +1151,15 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
   if (target == EXIT_BLOCK_PTR)
     {
 #ifdef HAVE_return
-       emit_jump_insn_after (gen_return (), BB_END (jump_block));
+       emit_jump_insn_after_noloc (gen_return (), BB_END (jump_block));
 #else
-       abort ();
+       gcc_unreachable ();
 #endif
     }
   else
     {
       rtx label = block_label (target);
-      emit_jump_insn_after (gen_jump (label), BB_END (jump_block));
+      emit_jump_insn_after_noloc (gen_jump (label), BB_END (jump_block));
       JUMP_LABEL (BB_END (jump_block)) = label;
       LABEL_NUSES (label)++;
     }
@@ -1171,7 +1185,7 @@ force_nonfallthru (edge e)
 
 /* Redirect edge even at the expense of creating new jump insn or
    basic block.  Return new basic block if created, NULL otherwise.
-   Abort if conversion is impossible.  */
+   Conversion must be possible.  */
 
 static basic_block
 rtl_redirect_edge_and_branch_force (edge e, basic_block target)
@@ -1196,7 +1210,7 @@ rtl_tidy_fallthru_edge (edge e)
 
   /* ??? In a late-running flow pass, other folks may have deleted basic
      blocks by nopping out blocks, leaving multiple BARRIERs between here
-     and the target label. They ought to be chastized and fixed.
+     and the target label. They ought to be chastised and fixed.
 
      We can also wind up with a sequence of undeletable labels between
      one block and the next.
@@ -1212,10 +1226,10 @@ rtl_tidy_fallthru_edge (edge e)
      If block B consisted only of this single jump, turn it into a deleted
      note.  */
   q = BB_END (b);
-  if (GET_CODE (q) == JUMP_INSN
+  if (JUMP_P (q)
       && onlyjump_p (q)
       && (any_uncondjump_p (q)
-         || (b->succ == e && e->succ_next == NULL)))
+         || single_succ_p (b)))
     {
 #ifdef HAVE_cc0
       /* If this was a conditional jump, we need to also delete
@@ -1228,7 +1242,7 @@ rtl_tidy_fallthru_edge (edge e)
 
       /* We don't want a block to end on a line-number note since that has
         the potential of changing the code between -g and not -g.  */
-      while (GET_CODE (q) == NOTE && NOTE_LINE_NUMBER (q) >= 0)
+      while (NOTE_P (q) && NOTE_LINE_NUMBER (q) >= 0)
        q = PREV_INSN (q);
     }
 
@@ -1262,7 +1276,7 @@ back_edge_of_syntactic_loop_p (basic_block bb1, basic_block bb2)
 
   for (insn = BB_END (bb1); insn != BB_HEAD (bb2) && count >= 0;
        insn = NEXT_INSN (insn))
-    if (GET_CODE (insn) == NOTE)
+    if (NOTE_P (insn))
       {
        if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
          count++;
@@ -1283,7 +1297,7 @@ rtl_move_block_after (basic_block bb ATTRIBUTE_UNUSED,
 }
 
 /* Split a (typically critical) edge.  Return the new block.
-   Abort on abnormal edges.
+   The edge must not be abnormal.
 
    ??? The code generally expects to be called on critical edges.
    The case of a block ending in an unconditional jump to a
@@ -1296,16 +1310,16 @@ rtl_split_edge (edge edge_in)
   rtx before;
 
   /* Abnormal edges cannot be split.  */
-  if ((edge_in->flags & EDGE_ABNORMAL) != 0)
-    abort ();
+  gcc_assert (!(edge_in->flags & EDGE_ABNORMAL));
 
   /* We are going to place the new block in front of edge destination.
      Avoid existence of fallthru predecessors.  */
   if ((edge_in->flags & EDGE_FALLTHRU) == 0)
     {
       edge e;
+      edge_iterator ei;
 
-      for (e = edge_in->dest->pred; e; e = e->pred_next)
+      FOR_EACH_EDGE (e, ei, edge_in->dest->preds)
        if (e->flags & EDGE_FALLTHRU)
          break;
 
@@ -1333,7 +1347,7 @@ rtl_split_edge (edge edge_in)
 
   if (edge_in->dest != EXIT_BLOCK_PTR
       && PREV_INSN (BB_HEAD (edge_in->dest))
-      && GET_CODE (PREV_INSN (BB_HEAD (edge_in->dest))) == NOTE
+      && NOTE_P (PREV_INSN (BB_HEAD (edge_in->dest)))
       && (NOTE_LINE_NUMBER (PREV_INSN (BB_HEAD (edge_in->dest)))
          == NOTE_INSN_LOOP_BEG)
       && !back_edge_of_syntactic_loop_p (edge_in->dest, edge_in->src))
@@ -1349,23 +1363,28 @@ rtl_split_edge (edge edge_in)
     {
       before = NEXT_INSN (BB_END (edge_in->src));
       if (before
-         && GET_CODE (before) == NOTE
+         && NOTE_P (before)
          && NOTE_LINE_NUMBER (before) == NOTE_INSN_LOOP_END)
        before = NEXT_INSN (before);
       bb = create_basic_block (before, NULL, edge_in->src);
+      BB_COPY_PARTITION (bb, edge_in->src);
     }
   else
-    bb = create_basic_block (before, NULL, edge_in->dest->prev_bb);
+    {
+      bb = create_basic_block (before, NULL, edge_in->dest->prev_bb);
+      /* ??? Why not edge_in->dest->prev_bb here?  */
+      BB_COPY_PARTITION (bb, edge_in->dest);
+    }
 
   /* ??? This info is likely going to be out of date very soon.  */
-  if (edge_in->dest->global_live_at_start)
+  if (edge_in->dest->il.rtl->global_live_at_start)
     {
-      bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
-      bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
-      COPY_REG_SET (bb->global_live_at_start,
-                   edge_in->dest->global_live_at_start);
-      COPY_REG_SET (bb->global_live_at_end,
-                   edge_in->dest->global_live_at_start);
+      bb->il.rtl->global_live_at_start = ALLOC_REG_SET (&reg_obstack);
+      bb->il.rtl->global_live_at_end = ALLOC_REG_SET (&reg_obstack);
+      COPY_REG_SET (bb->il.rtl->global_live_at_start,
+                   edge_in->dest->il.rtl->global_live_at_start);
+      COPY_REG_SET (bb->il.rtl->global_live_at_end,
+                   edge_in->dest->il.rtl->global_live_at_start);
     }
 
   make_single_succ_edge (bb, edge_in->dest, EDGE_FALLTHRU);
@@ -1374,8 +1393,8 @@ rtl_split_edge (edge edge_in)
      jump instruction to target our new block.  */
   if ((edge_in->flags & EDGE_FALLTHRU) == 0)
     {
-      if (!redirect_edge_and_branch (edge_in, bb))
-       abort ();
+      edge redirected = redirect_edge_and_branch (edge_in, bb);
+      gcc_assert (redirected);
     }
   else
     redirect_edge_succ (edge_in, bb);
@@ -1392,8 +1411,7 @@ insert_insn_on_edge (rtx pattern, edge e)
 {
   /* We cannot insert instructions on an abnormal critical edge.
      It will be easier to find the culprit if we die now.  */
-  if ((e->flags & EDGE_ABNORMAL) && EDGE_CRITICAL_P (e))
-    abort ();
+  gcc_assert (!((e->flags & EDGE_ABNORMAL) && EDGE_CRITICAL_P (e)));
 
   if (e->insns.r == NULL_RTX)
     start_sequence ();
@@ -1437,25 +1455,30 @@ bool
 safe_insert_insn_on_edge (rtx insn, edge e)
 {
   rtx x;
-  regset_head killed_head;
-  regset killed = INITIALIZE_REG_SET (killed_head);
+  regset killed;
   rtx save_regs = NULL_RTX;
-  int regno, noccmode;
+  unsigned regno;
   enum machine_mode mode;
+  reg_set_iterator rsi;
 
-#ifdef AVOID_CCMODE_COPIES
-  noccmode = true;
-#else
-  noccmode = false;
-#endif
+  killed = ALLOC_REG_SET (&reg_obstack);
 
   for (x = insn; x; x = NEXT_INSN (x))
     if (INSN_P (x))
       note_stores (PATTERN (x), mark_killed_regs, killed);
-  bitmap_operation (killed, killed, e->dest->global_live_at_start,
-                   BITMAP_AND);
 
-  EXECUTE_IF_SET_IN_REG_SET (killed, 0, regno,
+  /* Mark all hard registers as killed.  Register allocator/reload cannot
+     cope with the situation when life range of hard register spans operation
+     for that the appropriate register is needed, i.e. it would be unsafe to
+     extend the life ranges of hard registers.  */
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    if (!fixed_regs[regno]
+       && !REGNO_PTR_FRAME_P (regno))
+      SET_REGNO_REG_SET (killed, regno);
+
+  bitmap_and_into (killed, e->dest->il.rtl->global_live_at_start);
+
+  EXECUTE_IF_SET_IN_REG_SET (killed, 0, regno, rsi)
     {
       mode = regno < FIRST_PSEUDO_REGISTER
              ? reg_raw_mode[regno]
@@ -1463,7 +1486,8 @@ safe_insert_insn_on_edge (rtx insn, edge e)
       if (mode == VOIDmode)
        return false;
 
-      if (noccmode && mode == CCmode)
+      /* Avoid copying in CCmode if we can't.  */
+      if (!can_copy_p (mode))
        return false;
        
       save_regs = alloc_EXPR_LIST (0,
@@ -1471,7 +1495,7 @@ safe_insert_insn_on_edge (rtx insn, edge e)
                                                    gen_reg_rtx (mode),
                                                    gen_raw_REG (mode, regno)),
                                   save_regs);
-    });
+    }
 
   if (save_regs)
     {
@@ -1498,6 +1522,7 @@ safe_insert_insn_on_edge (rtx insn, edge e)
   insert_insn_on_edge (insn, e);
   
   FREE_REG_SET (killed);
+
   return true;
 }
 
@@ -1515,9 +1540,10 @@ commit_one_edge_insertion (edge e, int watch_calls)
 
   /* Special case -- avoid inserting code between call and storing
      its return value.  */
-  if (watch_calls && (e->flags & EDGE_FALLTHRU) && !e->dest->pred->pred_next
+  if (watch_calls && (e->flags & EDGE_FALLTHRU)
+      && single_pred_p (e->dest)
       && e->src != ENTRY_BLOCK_PTR
-      && GET_CODE (BB_END (e->src)) == CALL_INSN)
+      && CALL_P (BB_END (e->src)))
     {
       rtx next = next_nonnote_insn (BB_END (e->src));
 
@@ -1535,21 +1561,17 @@ commit_one_edge_insertion (edge e, int watch_calls)
     {
       /* Figure out where to put these things.  If the destination has
          one predecessor, insert there.  Except for the exit block.  */
-      if (e->dest->pred->pred_next == NULL && e->dest != EXIT_BLOCK_PTR)
+      if (single_pred_p (e->dest) && e->dest != EXIT_BLOCK_PTR)
        {
          bb = e->dest;
 
          /* Get the location correct wrt a code label, and "nice" wrt
             a basic block note, and before everything else.  */
          tmp = BB_HEAD (bb);
-         if (GET_CODE (tmp) == CODE_LABEL)
+         if (LABEL_P (tmp))
            tmp = NEXT_INSN (tmp);
          if (NOTE_INSN_BASIC_BLOCK_P (tmp))
            tmp = NEXT_INSN (tmp);
-         if (tmp 
-             && GET_CODE (tmp) == NOTE
-             && NOTE_LINE_NUMBER (tmp) == NOTE_INSN_UNLIKELY_EXECUTED_CODE)
-           tmp = NEXT_INSN (tmp);
          if (tmp == BB_HEAD (bb))
            before = tmp;
          else if (tmp)
@@ -1561,7 +1583,7 @@ commit_one_edge_insertion (edge e, int watch_calls)
       /* If the source has one successor and the edge is not abnormal,
          insert there.  Except for the entry block.  */
       else if ((e->flags & EDGE_ABNORMAL) == 0
-              && e->src->succ->succ_next == NULL
+              && single_succ_p (e->src)
               && e->src != ENTRY_BLOCK_PTR)
        {
          bb = e->src;
@@ -1572,17 +1594,17 @@ commit_one_edge_insertion (edge e, int watch_calls)
 
             We know this block has a single successor, so we can just emit
             the queued insns before the jump.  */
-         if (GET_CODE (BB_END (bb)) == JUMP_INSN)
+         if (JUMP_P (BB_END (bb)))
            for (before = BB_END (bb);
-                GET_CODE (PREV_INSN (before)) == NOTE
+                NOTE_P (PREV_INSN (before))
                 && NOTE_LINE_NUMBER (PREV_INSN (before)) ==
                 NOTE_INSN_LOOP_BEG; before = PREV_INSN (before))
              ;
          else
            {
-             /* We'd better be fallthru, or we've lost track of what's what.  */
-             if ((e->flags & EDGE_FALLTHRU) == 0)
-               abort ();
+             /* We'd better be fallthru, or we've lost track of
+                what's what.  */
+             gcc_assert (e->flags & EDGE_FALLTHRU);
 
              after = BB_END (bb);
            }
@@ -1593,36 +1615,29 @@ commit_one_edge_insertion (edge e, int watch_calls)
          bb = split_edge (e);
          after = BB_END (bb);
 
-         /* If we are partitioning hot/cold basic blocks, we must make sure
-            that the new basic block ends up in the correct section.  */
-
-         bb->partition = e->src->partition;
          if (flag_reorder_blocks_and_partition
+             && targetm.have_named_sections
              && e->src != ENTRY_BLOCK_PTR
-             && e->src->partition == COLD_PARTITION)
+             && BB_PARTITION (e->src) == BB_COLD_PARTITION
+             && !(e->flags & EDGE_CROSSING))
            {
-             rtx bb_note, new_note, cur_insn;
+             rtx bb_note, cur_insn;
 
              bb_note = NULL_RTX;
              for (cur_insn = BB_HEAD (bb); cur_insn != NEXT_INSN (BB_END (bb));
                   cur_insn = NEXT_INSN (cur_insn))
-               if (GET_CODE (cur_insn) == NOTE
+               if (NOTE_P (cur_insn)
                    && NOTE_LINE_NUMBER (cur_insn) == NOTE_INSN_BASIC_BLOCK)
                  {
                    bb_note = cur_insn;
                    break;
                  }
 
-             new_note = emit_note_after (NOTE_INSN_UNLIKELY_EXECUTED_CODE,
-                                         bb_note);
-             NOTE_BASIC_BLOCK (new_note) = bb;
-             if (GET_CODE (BB_END (bb)) == JUMP_INSN
+             if (JUMP_P (BB_END (bb))
                  && !any_condjump_p (BB_END (bb))
-                 && bb->succ->crossing_edge )
+                 && (single_succ_edge (bb)->flags & EDGE_CROSSING))
                REG_NOTES (BB_END (bb)) = gen_rtx_EXPR_LIST 
                  (REG_CROSSING_JUMP, NULL_RTX, REG_NOTES (BB_END (bb)));
-             if (after == bb_note)
-               after = new_note;
            }
        }
     }
@@ -1631,11 +1646,11 @@ commit_one_edge_insertion (edge e, int watch_calls)
 
   if (before)
     {
-      emit_insn_before (insns, before);
+      emit_insn_before_noloc (insns, before);
       last = prev_nonnote_insn (before);
     }
   else
-    last = emit_insn_after (insns, after);
+    last = emit_insn_after_noloc (insns, after);
 
   if (returnjump_p (last))
     {
@@ -1644,10 +1659,9 @@ commit_one_edge_insertion (edge e, int watch_calls)
          for the (single) epilogue, which already has a fallthru edge
          to EXIT.  */
 
-      e = bb->succ;
-      if (e->dest != EXIT_BLOCK_PTR
-         || e->succ_next != NULL || (e->flags & EDGE_FALLTHRU) == 0)
-       abort ();
+      e = single_succ_edge (bb);
+      gcc_assert (e->dest == EXIT_BLOCK_PTR
+                 && single_succ_p (bb) && (e->flags & EDGE_FALLTHRU));
 
       e->flags &= ~EDGE_FALLTHRU;
       emit_barrier_after (last);
@@ -1655,10 +1669,10 @@ commit_one_edge_insertion (edge e, int watch_calls)
       if (before)
        delete_insn (before);
     }
-  else if (GET_CODE (last) == JUMP_INSN)
-    abort ();
+  else
+    gcc_assert (!JUMP_P (last));
 
-  /* Mark the basic block for find_sub_basic_blocks.  */
+  /* Mark the basic block for find_many_sub_basic_blocks.  */
   bb->aux = &bb->aux;
 }
 
@@ -1677,17 +1691,15 @@ commit_edge_insertions (void)
 
   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
     {
-      edge e, next;
+      edge e;
+      edge_iterator ei;
 
-      for (e = bb->succ; e; e = next)
-       {
-         next = e->succ_next;
-         if (e->insns.r)
-           {
-             changed = true;
-             commit_one_edge_insertion (e, false);
-           }
-       }
+      FOR_EACH_EDGE (e, ei, bb->succs)
+       if (e->insns.r)
+         {
+           changed = true;
+           commit_one_edge_insertion (e, false);
+         }
     }
 
   if (!changed)
@@ -1701,8 +1713,7 @@ commit_edge_insertions (void)
         SET_BIT (blocks, bb->index);
        /* Check for forgotten bb->aux values before commit_edge_insertions
           call.  */
-       if (bb->aux != &bb->aux)
-         abort ();
+       gcc_assert (bb->aux == &bb->aux);
        bb->aux = NULL;
       }
   find_many_sub_basic_blocks (blocks);
@@ -1725,17 +1736,15 @@ commit_edge_insertions_watch_calls (void)
 
   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
     {
-      edge e, next;
+      edge e;
+      edge_iterator ei;
 
-      for (e = bb->succ; e; e = next)
-       {
-         next = e->succ_next;
-         if (e->insns.r)
-           {
-             changed = true;
-             commit_one_edge_insertion (e, true);
-           }
-       }
+      FOR_EACH_EDGE (e, ei, bb->succs)
+       if (e->insns.r)
+         {
+           changed = true;
+           commit_one_edge_insertion (e, true);
+         }
     }
 
   if (!changed)
@@ -1749,8 +1758,7 @@ commit_edge_insertions_watch_calls (void)
         SET_BIT (blocks, bb->index);
        /* Check for forgotten bb->aux values before commit_edge_insertions
           call.  */
-       if (bb->aux != &bb->aux)
-         abort ();
+       gcc_assert (bb->aux == &bb->aux);
        bb->aux = NULL;
       }
   find_many_sub_basic_blocks (blocks);
@@ -1772,7 +1780,7 @@ rtl_dump_bb (basic_block bb, FILE *outf, int indent)
   s_indent[indent] = '\0';
 
   fprintf (outf, ";;%s Registers live at start: ", s_indent);
-  dump_regset (bb->global_live_at_start, outf);
+  dump_regset (bb->il.rtl->global_live_at_start, outf);
   putc ('\n', outf);
 
   for (insn = BB_HEAD (bb), last = NEXT_INSN (BB_END (bb)); insn != last;
@@ -1780,7 +1788,7 @@ rtl_dump_bb (basic_block bb, FILE *outf, int indent)
     print_rtl_single (outf, insn);
 
   fprintf (outf, ";;%s Registers live at end: ", s_indent);
-  dump_regset (bb->global_live_at_end, outf);
+  dump_regset (bb->il.rtl->global_live_at_end, outf);
   putc ('\n', outf);
 }
 \f
@@ -1831,13 +1839,13 @@ print_rtl_with_bb (FILE *outf, rtx rtx_first)
            {
              fprintf (outf, ";; Start of basic block %d, registers live:",
                       bb->index);
-             dump_regset (bb->global_live_at_start, outf);
+             dump_regset (bb->il.rtl->global_live_at_start, outf);
              putc ('\n', outf);
            }
 
          if (in_bb_p[INSN_UID (tmp_rtx)] == NOT_IN_BB
-             && GET_CODE (tmp_rtx) != NOTE
-             && GET_CODE (tmp_rtx) != BARRIER)
+             && !NOTE_P (tmp_rtx)
+             && !BARRIER_P (tmp_rtx))
            fprintf (outf, ";; Insn is not within a basic block\n");
          else if (in_bb_p[INSN_UID (tmp_rtx)] == IN_MULTIPLE_BB)
            fprintf (outf, ";; Insn is in multiple basic blocks\n");
@@ -1848,7 +1856,7 @@ print_rtl_with_bb (FILE *outf, rtx rtx_first)
            {
              fprintf (outf, ";; End of basic block %d, registers live:\n",
                       bb->index);
-             dump_regset (bb->global_live_at_end, outf);
+             dump_regset (bb->il.rtl->global_live_at_end, outf);
              putc ('\n', outf);
            }
 
@@ -1874,7 +1882,7 @@ void
 update_br_prob_note (basic_block bb)
 {
   rtx note;
-  if (GET_CODE (BB_END (bb)) != JUMP_INSN)
+  if (!JUMP_P (BB_END (bb)))
     return;
   note = find_reg_note (BB_END (bb), REG_BR_PROB, NULL_RTX);
   if (!note || INTVAL (XEXP (note, 0)) == BRANCH_EDGE (bb)->probability)
@@ -1906,13 +1914,10 @@ rtl_verify_flow_info_1 (void)
   basic_block *bb_info;
   rtx x;
   int err = 0;
-  basic_block bb, last_bb_seen;
+  basic_block bb;
 
   bb_info = xcalloc (max_uid, sizeof (basic_block));
 
-  /* Check bb chain & numbers.  */
-  last_bb_seen = ENTRY_BLOCK_PTR;
-
   FOR_EACH_BB_REVERSE (bb)
     {
       rtx head = BB_HEAD (bb);
@@ -1923,6 +1928,12 @@ rtl_verify_flow_info_1 (void)
        if (x == end)
          break;
 
+      if (!(bb->flags & BB_RTL))
+       {
+         error ("BB_RTL flag not set for block %d", bb->index);
+         err = 1;
+       }
+
       if (!x)
        {
          error ("end insn %d for block %d not found in the insn stream",
@@ -1965,27 +1976,32 @@ rtl_verify_flow_info_1 (void)
       int n_fallthru = 0, n_eh = 0, n_call = 0, n_abnormal = 0, n_branch = 0;
       edge e, fallthru = NULL;
       rtx note;
+      edge_iterator ei;
 
-      if (INSN_P (BB_END (bb))
+      if (JUMP_P (BB_END (bb))
          && (note = find_reg_note (BB_END (bb), REG_BR_PROB, NULL_RTX))
-         && bb->succ && bb->succ->succ_next
+         && EDGE_COUNT (bb->succs) >= 2
          && any_condjump_p (BB_END (bb)))
        {
-         if (INTVAL (XEXP (note, 0)) != BRANCH_EDGE (bb)->probability)
+         if (INTVAL (XEXP (note, 0)) != BRANCH_EDGE (bb)->probability
+             && profile_status != PROFILE_ABSENT)
            {
              error ("verify_flow_info: REG_BR_PROB does not match cfg %wi %i",
                     INTVAL (XEXP (note, 0)), BRANCH_EDGE (bb)->probability);
              err = 1;
            }
        }
-      for (e = bb->succ; e; e = e->succ_next)
+      FOR_EACH_EDGE (e, ei, bb->succs)
        {
          if (e->flags & EDGE_FALLTHRU)
            {
              n_fallthru++, fallthru = e;
-             if (e->crossing_edge)
-               { 
-                 error ("Fallthru edge crosses section boundary (bb %i)",
+             if ((e->flags & EDGE_CROSSING)
+                 || (BB_PARTITION (e->src) != BB_PARTITION (e->dest)
+                     && e->src != ENTRY_BLOCK_PTR
+                     && e->dest != EXIT_BLOCK_PTR))
+           { 
+                 error ("fallthru edge crosses section boundary (bb %i)",
                         e->src->index);
                  err = 1;
                }
@@ -1994,7 +2010,8 @@ rtl_verify_flow_info_1 (void)
          if ((e->flags & ~(EDGE_DFS_BACK
                            | EDGE_CAN_FALLTHRU
                            | EDGE_IRREDUCIBLE_LOOP
-                           | EDGE_LOOP_EXIT)) == 0)
+                           | EDGE_LOOP_EXIT
+                           | EDGE_CROSSING)) == 0)
            n_branch++;
 
          if (e->flags & EDGE_ABNORMAL_CALL)
@@ -2009,50 +2026,52 @@ rtl_verify_flow_info_1 (void)
       if (n_eh && GET_CODE (PATTERN (BB_END (bb))) != RESX
          && !find_reg_note (BB_END (bb), REG_EH_REGION, NULL_RTX))
        {
-         error ("Missing REG_EH_REGION note in the end of bb %i", bb->index);
+         error ("missing REG_EH_REGION note in the end of bb %i", bb->index);
          err = 1;
        }
       if (n_branch
-         && (GET_CODE (BB_END (bb)) != JUMP_INSN
+         && (!JUMP_P (BB_END (bb))
              || (n_branch > 1 && (any_uncondjump_p (BB_END (bb))
                                   || any_condjump_p (BB_END (bb))))))
        {
-         error ("Too many outgoing branch edges from bb %i", bb->index);
+         error ("too many outgoing branch edges from bb %i", bb->index);
          err = 1;
        }
       if (n_fallthru && any_uncondjump_p (BB_END (bb)))
        {
-         error ("Fallthru edge after unconditional jump %i", bb->index);
+         error ("fallthru edge after unconditional jump %i", bb->index);
          err = 1;
        }
       if (n_branch != 1 && any_uncondjump_p (BB_END (bb)))
        {
-         error ("Wrong amount of branch edges after unconditional jump %i", bb->index);
+         error ("wrong amount of branch edges after unconditional jump %i", bb->index);
          err = 1;
        }
       if (n_branch != 1 && any_condjump_p (BB_END (bb))
-         && JUMP_LABEL (BB_END (bb)) != BB_HEAD (fallthru->dest))
+         && JUMP_LABEL (BB_END (bb)) == BB_HEAD (fallthru->dest))
        {
-         error ("Wrong amount of branch edges after conditional jump %i", bb->index);
+         error ("wrong amount of branch edges after conditional jump %i", bb->index);
          err = 1;
        }
-      if (n_call && GET_CODE (BB_END (bb)) != CALL_INSN)
+      if (n_call && !CALL_P (BB_END (bb)))
        {
-         error ("Call edges for non-call insn in bb %i", bb->index);
+         error ("call edges for non-call insn in bb %i", bb->index);
          err = 1;
        }
       if (n_abnormal
-         && (GET_CODE (BB_END (bb)) != CALL_INSN && n_call != n_abnormal)
-         && (GET_CODE (BB_END (bb)) != JUMP_INSN
+         && (!CALL_P (BB_END (bb)) && n_call != n_abnormal)
+         && (!JUMP_P (BB_END (bb))
              || any_condjump_p (BB_END (bb))
              || any_uncondjump_p (BB_END (bb))))
        {
-         error ("Abnormal edges for no purpose in bb %i", bb->index);
+         error ("abnormal edges for no purpose in bb %i", bb->index);
          err = 1;
        }
 
       for (x = BB_HEAD (bb); x != NEXT_INSN (BB_END (bb)); x = NEXT_INSN (x))
-       if (BLOCK_FOR_INSN (x) != bb)
+       /* We may have a barrier inside a basic block before dead code
+          elimination.  There is no BLOCK_FOR_INSN field in a barrier.  */
+       if (!BARRIER_P (x) && BLOCK_FOR_INSN (x) != bb)
          {
            debug_rtx (x);
            if (! BLOCK_FOR_INSN (x))
@@ -2071,7 +2090,7 @@ rtl_verify_flow_info_1 (void)
          block.  It ought to contain optional CODE_LABEL followed
         by NOTE_BASIC_BLOCK.  */
       x = BB_HEAD (bb);
-      if (GET_CODE (x) == CODE_LABEL)
+      if (LABEL_P (x))
        {
          if (BB_END (bb) == x)
            {
@@ -2091,7 +2110,7 @@ rtl_verify_flow_info_1 (void)
        }
 
       if (BB_END (bb) == x)
-       /* Do checks for empty blocks her. e */
+       /* Do checks for empty blocks here.  */
        ;
       else
        for (x = NEXT_INSN (x); x; x = NEXT_INSN (x))
@@ -2141,7 +2160,15 @@ rtl_verify_flow_info (void)
   FOR_EACH_BB_REVERSE (bb)
     {
       edge e;
-      for (e = bb->succ; e; e = e->succ_next)
+      edge_iterator ei;
+
+      if (bb->predictions)
+       {
+         error ("bb prediction set for block %i, but it is not used in RTL land", bb->index);
+         err = 1;
+       }
+
+      FOR_EACH_EDGE (e, ei, bb->succs)
        if (e->flags & EDGE_FALLTHRU)
          break;
       if (!e)
@@ -2149,10 +2176,10 @@ rtl_verify_flow_info (void)
          rtx insn;
 
          /* Ensure existence of barrier in BB with no fallthru edges.  */
-         for (insn = BB_END (bb); !insn || GET_CODE (insn) != BARRIER;
+         for (insn = BB_END (bb); !insn || !BARRIER_P (insn);
               insn = NEXT_INSN (insn))
            if (!insn
-               || (GET_CODE (insn) == NOTE
+               || (NOTE_P (insn)
                    && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK))
                {
                  error ("missing barrier after block %i", bb->index);
@@ -2175,13 +2202,7 @@ rtl_verify_flow_info (void)
          else
            for (insn = NEXT_INSN (BB_END (e->src)); insn != BB_HEAD (e->dest);
                 insn = NEXT_INSN (insn))
-             if (GET_CODE (insn) == BARRIER
-#ifndef CASE_DROPS_THROUGH
-                 || INSN_P (insn)
-#else
-                 || (INSN_P (insn) && ! JUMP_TABLE_DATA_P (insn))
-#endif
-                 )
+             if (BARRIER_P (insn) || INSN_P (insn))
                {
                  error ("verify_flow_info: Incorrect fallthru %i->%i",
                         e->src->index, e->dest->index);
@@ -2218,7 +2239,7 @@ rtl_verify_flow_info (void)
            case CODE_LABEL:
              /* An addr_vec is placed outside any basic block.  */
              if (NEXT_INSN (x)
-                 && GET_CODE (NEXT_INSN (x)) == JUMP_INSN
+                 && JUMP_P (NEXT_INSN (x))
                  && (GET_CODE (PATTERN (NEXT_INSN (x))) == ADDR_DIFF_VEC
                      || GET_CODE (PATTERN (NEXT_INSN (x))) == ADDR_VEC))
                x = NEXT_INSN (x);
@@ -2231,16 +2252,15 @@ rtl_verify_flow_info (void)
            }
        }
 
-      if (INSN_P (x)
-         && GET_CODE (x) == JUMP_INSN
+      if (JUMP_P (x)
          && returnjump_p (x) && ! condjump_p (x)
-         && ! (NEXT_INSN (x) && GET_CODE (NEXT_INSN (x)) == BARRIER))
+         && ! (NEXT_INSN (x) && BARRIER_P (NEXT_INSN (x))))
            fatal_insn ("return not followed by barrier", x);
       if (curr_bb && x == BB_END (curr_bb))
        curr_bb = NULL;
     }
 
-  if (num_bb_notes != n_basic_blocks)
+  if (num_bb_notes != n_basic_blocks - NUM_FIXED_BLOCKS)
     internal_error
       ("number of bb notes in insn chain (%d) != n_basic_blocks (%d)",
        num_bb_notes, n_basic_blocks);
@@ -2255,12 +2275,14 @@ rtl_verify_flow_info (void)
 bool
 purge_dead_edges (basic_block bb)
 {
-  edge e, next;
+  edge e;
   rtx insn = BB_END (bb), note;
   bool purged = false;
+  bool found;
+  edge_iterator ei;
 
   /* If this instruction cannot trap, remove REG_EH_REGION notes.  */
-  if (GET_CODE (insn) == INSN
+  if (NONJUMP_INSN_P (insn)
       && (note = find_reg_note (insn, REG_EH_REGION, NULL)))
     {
       rtx eqnote;
@@ -2272,33 +2294,48 @@ purge_dead_edges (basic_block bb)
     }
 
   /* Cleanup abnormal edges caused by exceptions or non-local gotos.  */
-  for (e = bb->succ; e; e = next)
+  for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
     {
-      next = e->succ_next;
+      /* There are three types of edges we need to handle correctly here: EH
+        edges, abnormal call EH edges, and abnormal call non-EH edges.  The
+        latter can appear when nonlocal gotos are used.  */
       if (e->flags & EDGE_EH)
        {
-         if (can_throw_internal (BB_END (bb)))
-           continue;
+         if (can_throw_internal (BB_END (bb))
+             /* If this is a call edge, verify that this is a call insn.  */
+             && (! (e->flags & EDGE_ABNORMAL_CALL)
+                 || CALL_P (BB_END (bb))))
+           {
+             ei_next (&ei);
+             continue;
+           }
        }
       else if (e->flags & EDGE_ABNORMAL_CALL)
        {
-         if (GET_CODE (BB_END (bb)) == CALL_INSN
+         if (CALL_P (BB_END (bb))
              && (! (note = find_reg_note (insn, REG_EH_REGION, NULL))
                  || INTVAL (XEXP (note, 0)) >= 0))
-           continue;
+           {
+             ei_next (&ei);
+             continue;
+           }
        }
       else
-       continue;
+       {
+         ei_next (&ei);
+         continue;
+       }
 
       remove_edge (e);
       bb->flags |= BB_DIRTY;
       purged = true;
     }
 
-  if (GET_CODE (insn) == JUMP_INSN)
+  if (JUMP_P (insn))
     {
       rtx note;
       edge b,f;
+      edge_iterator ei;
 
       /* We do care only about conditional jumps and simplejumps.  */
       if (!any_condjump_p (insn)
@@ -2317,10 +2354,8 @@ purge_dead_edges (basic_block bb)
            remove_note (insn, note);
        }
 
-      for (e = bb->succ; e; e = next)
+      for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
        {
-         next = e->succ_next;
-
          /* Avoid abnormal flags to leak from computed jumps turned
             into simplejumps.  */
 
@@ -2330,22 +2365,32 @@ purge_dead_edges (basic_block bb)
          if ((e->flags & EDGE_FALLTHRU) && any_condjump_p (insn))
            /* A conditional jump can fall through into the next
               block, so we should keep the edge.  */
-           continue;
+           {
+             ei_next (&ei);
+             continue;
+           }
          else if (e->dest != EXIT_BLOCK_PTR
                   && BB_HEAD (e->dest) == JUMP_LABEL (insn))
            /* If the destination block is the target of the jump,
               keep the edge.  */
-           continue;
+           {
+             ei_next (&ei);
+             continue;
+           }
          else if (e->dest == EXIT_BLOCK_PTR && returnjump_p (insn))
            /* If the destination block is the exit block, and this
               instruction is a return, then keep the edge.  */
-           continue;
+           {
+             ei_next (&ei);
+             continue;
+           }
          else if ((e->flags & EDGE_EH) && can_throw_internal (insn))
            /* Keep the edges that correspond to exceptions thrown by
               this instruction and rematerialize the EDGE_ABNORMAL
               flag we just cleared above.  */
            {
              e->flags |= EDGE_ABNORMAL;
+             ei_next (&ei);
              continue;
            }
 
@@ -2355,7 +2400,7 @@ purge_dead_edges (basic_block bb)
          remove_edge (e);
        }
 
-      if (!bb->succ || !purged)
+      if (EDGE_COUNT (bb->succs) == 0 || !purged)
        return purged;
 
       if (dump_file)
@@ -2365,10 +2410,10 @@ purge_dead_edges (basic_block bb)
        return purged;
 
       /* Redistribute probabilities.  */
-      if (!bb->succ->succ_next)
+      if (single_succ_p (bb))
        {
-         bb->succ->probability = REG_BR_PROB_BASE;
-         bb->succ->count = bb->count;
+         single_succ_edge (bb)->probability = REG_BR_PROB_BASE;
+         single_succ_edge (bb)->count = bb->count;
        }
       else
        {
@@ -2386,16 +2431,15 @@ purge_dead_edges (basic_block bb)
 
       return purged;
     }
-  else if (GET_CODE (insn) == CALL_INSN && SIBLING_CALL_P (insn))
+  else if (CALL_P (insn) && SIBLING_CALL_P (insn))
     {
       /* First, there should not be any EH or ABCALL edges resulting
         from non-local gotos and the like.  If there were, we shouldn't
         have created the sibcall in the first place.  Second, there
         should of course never have been a fallthru edge.  */
-      if (!bb->succ || bb->succ->succ_next)
-       abort ();
-      if (bb->succ->flags != (EDGE_SIBCALL | EDGE_ABNORMAL))
-       abort ();
+      gcc_assert (single_succ_p (bb));
+      gcc_assert (single_succ_edge (bb)->flags
+                 == (EDGE_SIBCALL | EDGE_ABNORMAL));
 
       return 0;
     }
@@ -2405,29 +2449,36 @@ purge_dead_edges (basic_block bb)
      as these are only created by conditional branches.  If we find such an
      edge we know that there used to be a jump here and can then safely
      remove all non-fallthru edges.  */
-  for (e = bb->succ; e && (e->flags & (EDGE_COMPLEX | EDGE_FALLTHRU));
-       e = e->succ_next)
-    ;
+  found = false;
+  FOR_EACH_EDGE (e, ei, bb->succs)
+    if (! (e->flags & (EDGE_COMPLEX | EDGE_FALLTHRU)))
+      {
+       found = true;
+       break;
+      }
 
-  if (!e)
+  if (!found)
     return purged;
 
-  for (e = bb->succ; e; e = next)
+  /* Remove all but the fake and fallthru edges.  The fake edge may be
+     the only successor for this block in the case of noreturn
+     calls.  */
+  for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
     {
-      next = e->succ_next;
-      if (!(e->flags & EDGE_FALLTHRU))
+      if (!(e->flags & (EDGE_FALLTHRU | EDGE_FAKE)))
        {
          bb->flags |= BB_DIRTY;
          remove_edge (e);
          purged = true;
        }
+      else
+       ei_next (&ei);
     }
 
-  if (!bb->succ || bb->succ->succ_next)
-    abort ();
+  gcc_assert (single_succ_p (bb));
 
-  bb->succ->probability = REG_BR_PROB_BASE;
-  bb->succ->count = bb->count;
+  single_succ_edge (bb)->probability = REG_BR_PROB_BASE;
+  single_succ_edge (bb)->count = bb->count;
 
   if (dump_file)
     fprintf (dump_file, "Purged non-fallthru edges from bb %i\n",
@@ -2439,34 +2490,18 @@ purge_dead_edges (basic_block bb)
    true if some edge has been eliminated.  */
 
 bool
-purge_all_dead_edges (int update_life_p)
+purge_all_dead_edges (void)
 {
   int purged = false;
-  sbitmap blocks = 0;
   basic_block bb;
 
-  if (update_life_p)
-    {
-      blocks = sbitmap_alloc (last_basic_block);
-      sbitmap_zero (blocks);
-    }
-
   FOR_EACH_BB (bb)
     {
       bool purged_here = purge_dead_edges (bb);
 
       purged |= purged_here;
-      if (purged_here && update_life_p)
-       SET_BIT (blocks, bb->index);
     }
 
-  if (update_life_p && purged)
-    update_life_info (blocks, UPDATE_LIFE_GLOBAL,
-                     PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
-                     | PROP_KILL_DEAD_CODE);
-
-  if (update_life_p)
-    sbitmap_free (blocks);
   return purged;
 }
 
@@ -2478,8 +2513,8 @@ cfg_layout_split_block (basic_block bb, void *insnp)
   rtx insn = insnp;
   basic_block new_bb = rtl_split_block (bb, insn);
 
-  new_bb->rbi->footer = bb->rbi->footer;
-  bb->rbi->footer = NULL;
+  new_bb->il.rtl->footer = bb->il.rtl->footer;
+  bb->il.rtl->footer = NULL;
 
   return new_bb;
 }
@@ -2524,27 +2559,30 @@ cfg_layout_redirect_edge_and_branch (edge e, basic_block dest)
   if (e->flags & EDGE_FALLTHRU)
     {
       /* Redirect any branch edges unified with the fallthru one.  */
-      if (GET_CODE (BB_END (src)) == JUMP_INSN
+      if (JUMP_P (BB_END (src))
          && label_is_jump_target_p (BB_HEAD (e->dest),
                                     BB_END (src)))
        {
+         edge redirected;
+         
          if (dump_file)
            fprintf (dump_file, "Fallthru edge unified with branch "
                     "%i->%i redirected to %i\n",
                     e->src->index, e->dest->index, dest->index);
          e->flags &= ~EDGE_FALLTHRU;
-         if (!redirect_branch_edge (e, dest))
-           abort ();
+         redirected = redirect_branch_edge (e, dest);
+         gcc_assert (redirected);
          e->flags |= EDGE_FALLTHRU;
           e->src->flags |= BB_DIRTY;
          return e;
        }
       /* In case we are redirecting fallthru edge to the branch edge
          of conditional jump, remove it.  */
-      if (src->succ->succ_next
-         && !src->succ->succ_next->succ_next)
+      if (EDGE_COUNT (src->succs) == 2)
        {
-         edge s = e->succ_next ? e->succ_next : src->succ;
+         /* Find the edge that is different from E.  */
+         edge s = EDGE_SUCC (src, EDGE_SUCC (src, 0) == e);
+
          if (s->dest == dest
              && any_condjump_p (BB_END (src))
              && onlyjump_p (BB_END (src)))
@@ -2559,8 +2597,7 @@ cfg_layout_redirect_edge_and_branch (edge e, basic_block dest)
     ret = redirect_branch_edge (e, dest);
 
   /* We don't want simplejumps in the insn stream during cfglayout.  */
-  if (simplejump_p (BB_END (src)))
-    abort ();
+  gcc_assert (!simplejump_p (BB_END (src)));
 
   src->flags |= BB_DIRTY;
   return ret;
@@ -2570,8 +2607,9 @@ cfg_layout_redirect_edge_and_branch (edge e, basic_block dest)
 static basic_block
 cfg_layout_redirect_edge_and_branch_force (edge e, basic_block dest)
 {
-  if (!cfg_layout_redirect_edge_and_branch (e, dest))
-    abort ();
+  edge redirected = cfg_layout_redirect_edge_and_branch (e, dest);
+
+  gcc_assert (redirected);
   return NULL;
 }
 
@@ -2582,44 +2620,44 @@ cfg_layout_delete_block (basic_block bb)
 {
   rtx insn, next, prev = PREV_INSN (BB_HEAD (bb)), *to, remaints;
 
-  if (bb->rbi->header)
+  if (bb->il.rtl->header)
     {
       next = BB_HEAD (bb);
       if (prev)
-       NEXT_INSN (prev) = bb->rbi->header;
+       NEXT_INSN (prev) = bb->il.rtl->header;
       else
-       set_first_insn (bb->rbi->header);
-      PREV_INSN (bb->rbi->header) = prev;
-      insn = bb->rbi->header;
+       set_first_insn (bb->il.rtl->header);
+      PREV_INSN (bb->il.rtl->header) = prev;
+      insn = bb->il.rtl->header;
       while (NEXT_INSN (insn))
        insn = NEXT_INSN (insn);
       NEXT_INSN (insn) = next;
       PREV_INSN (next) = insn;
     }
   next = NEXT_INSN (BB_END (bb));
-  if (bb->rbi->footer)
+  if (bb->il.rtl->footer)
     {
-      insn = bb->rbi->footer;
+      insn = bb->il.rtl->footer;
       while (insn)
        {
-         if (GET_CODE (insn) == BARRIER)
+         if (BARRIER_P (insn))
            {
              if (PREV_INSN (insn))
                NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
              else
-               bb->rbi->footer = NEXT_INSN (insn);
+               bb->il.rtl->footer = NEXT_INSN (insn);
              if (NEXT_INSN (insn))
                PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
            }
-         if (GET_CODE (insn) == CODE_LABEL)
+         if (LABEL_P (insn))
            break;
          insn = NEXT_INSN (insn);
        }
-      if (bb->rbi->footer)
+      if (bb->il.rtl->footer)
        {
          insn = BB_END (bb);
-         NEXT_INSN (insn) = bb->rbi->footer;
-         PREV_INSN (bb->rbi->footer) = insn;
+         NEXT_INSN (insn) = bb->il.rtl->footer;
+         PREV_INSN (bb->il.rtl->footer) = insn;
          while (NEXT_INSN (insn))
            insn = NEXT_INSN (insn);
          NEXT_INSN (insn) = next;
@@ -2630,9 +2668,10 @@ cfg_layout_delete_block (basic_block bb)
        }
     }
   if (bb->next_bb != EXIT_BLOCK_PTR)
-    to = &bb->next_bb->rbi->header;
+    to = &bb->next_bb->il.rtl->header;
   else
     to = &cfg_layout_function_footer;
+
   rtl_delete_block (bb);
 
   if (prev)
@@ -2661,60 +2700,67 @@ cfg_layout_delete_block (basic_block bb)
 static bool
 cfg_layout_can_merge_blocks_p (basic_block a, basic_block b)
 {
-  bool partitions_ok = true;
-
   /* If we are partitioning hot/cold basic blocks, we don't want to
      mess up unconditional or indirect jumps that cross between hot
-     and cold sections.  */
-  
-  if (flag_reorder_blocks_and_partition
-      && (find_reg_note (BB_END (a), REG_CROSSING_JUMP, NULL_RTX)
-         || find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX)
-         || a->partition != b->partition))
-    partitions_ok = false;
+     and cold sections.
+
+     Basic block partitioning may result in some jumps that appear to
+     be optimizable (or blocks that appear to be mergeable), but which really 
+     must be left untouched (they are required to make it safely across 
+     partition boundaries).  See  the comments at the top of 
+     bb-reorder.c:partition_hot_cold_basic_blocks for complete details.  */
+
+  if (BB_PARTITION (a) != BB_PARTITION (b))
+    return false;
 
   /* There must be exactly one edge in between the blocks.  */
-  return (a->succ && !a->succ->succ_next && a->succ->dest == b
-         && !b->pred->pred_next && a != b
+  return (single_succ_p (a)
+         && single_succ (a) == b
+         && single_pred_p (b) == 1
+         && a != b
          /* Must be simple edge.  */
-         && !(a->succ->flags & EDGE_COMPLEX)
-         && partitions_ok
+         && !(single_succ_edge (a)->flags & EDGE_COMPLEX)
          && a != ENTRY_BLOCK_PTR && b != EXIT_BLOCK_PTR
          /* If the jump insn has side effects,
             we can't kill the edge.  */
-         && (GET_CODE (BB_END (a)) != JUMP_INSN
+         && (!JUMP_P (BB_END (a))
              || (reload_completed
                  ? simplejump_p (BB_END (a)) : onlyjump_p (BB_END (a)))));
 }
 
-/* Merge block A and B, abort when it is not possible.  */
+/* Merge block A and B.  The blocks must be mergeable.  */
+
 static void
 cfg_layout_merge_blocks (basic_block a, basic_block b)
 {
 #ifdef ENABLE_CHECKING
-  if (!cfg_layout_can_merge_blocks_p (a, b))
-    abort ();
+  gcc_assert (cfg_layout_can_merge_blocks_p (a, b));
 #endif
 
   /* If there was a CODE_LABEL beginning B, delete it.  */
-  if (GET_CODE (BB_HEAD (b)) == CODE_LABEL)
-    delete_insn (BB_HEAD (b));
+  if (LABEL_P (BB_HEAD (b)))
+    {
+      /* This might have been an EH label that no longer has incoming
+        EH edges.  Update data structures to match.  */
+      maybe_remove_eh_handler (BB_HEAD (b));
+      delete_insn (BB_HEAD (b));
+    }
 
   /* We should have fallthru edge in a, or we can do dummy redirection to get
      it cleaned up.  */
-  if (GET_CODE (BB_END (a)) == JUMP_INSN)
-    try_redirect_by_replacing_jump (a->succ, b, true);
-  if (GET_CODE (BB_END (a)) == JUMP_INSN)
-    abort ();
+  if (JUMP_P (BB_END (a)))
+    try_redirect_by_replacing_jump (EDGE_SUCC (a, 0), b, true);
+  gcc_assert (!JUMP_P (BB_END (a)));
 
   /* Possible line number notes should appear in between.  */
-  if (b->rbi->header)
+  if (b->il.rtl->header)
     {
       rtx first = BB_END (a), last;
 
-      last = emit_insn_after (b->rbi->header, BB_END (a));
+      last = emit_insn_after_noloc (b->il.rtl->header, BB_END (a));
       delete_insn_chain (NEXT_INSN (first), last);
-      b->rbi->header = NULL;
+      b->il.rtl->header = NULL;
     }
 
   /* In the case basic blocks are not adjacent, move them around.  */
@@ -2722,12 +2768,11 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
     {
       rtx first = unlink_insn_chain (BB_HEAD (b), BB_END (b));
 
-      emit_insn_after (first, BB_END (a));
+      emit_insn_after_noloc (first, BB_END (a));
       /* Skip possible DELETED_LABEL insn.  */
       if (!NOTE_INSN_BASIC_BLOCK_P (first))
        first = NEXT_INSN (first);
-      if (!NOTE_INSN_BASIC_BLOCK_P (first))
-       abort ();
+      gcc_assert (NOTE_INSN_BASIC_BLOCK_P (first));
       BB_HEAD (b) = NULL;
       delete_insn (first);
     }
@@ -2744,29 +2789,29 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
       /* Skip possible DELETED_LABEL insn.  */
       if (!NOTE_INSN_BASIC_BLOCK_P (insn))
        insn = NEXT_INSN (insn);
-      if (!NOTE_INSN_BASIC_BLOCK_P (insn))
-       abort ();
+      gcc_assert (NOTE_INSN_BASIC_BLOCK_P (insn));
       BB_HEAD (b) = NULL;
       BB_END (a) = BB_END (b);
       delete_insn (insn);
     }
 
   /* Possible tablejumps and barriers should appear after the block.  */
-  if (b->rbi->footer)
+  if (b->il.rtl->footer)
     {
-      if (!a->rbi->footer)
-       a->rbi->footer = b->rbi->footer;
+      if (!a->il.rtl->footer)
+       a->il.rtl->footer = b->il.rtl->footer;
       else
        {
-         rtx last = a->rbi->footer;
+         rtx last = a->il.rtl->footer;
 
          while (NEXT_INSN (last))
            last = NEXT_INSN (last);
-         NEXT_INSN (last) = b->rbi->footer;
-         PREV_INSN (b->rbi->footer) = last;
+         NEXT_INSN (last) = b->il.rtl->footer;
+         PREV_INSN (b->il.rtl->footer) = last;
        }
-      b->rbi->footer = NULL;
+      b->il.rtl->footer = NULL;
     }
+  a->il.rtl->global_live_at_end = b->il.rtl->global_live_at_end;
 
   if (dump_file)
     fprintf (dump_file, "Merged blocks %d and %d.\n",
@@ -2778,13 +2823,24 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
 static basic_block
 cfg_layout_split_edge (edge e)
 {
-  edge new_e;
   basic_block new_bb =
     create_basic_block (e->src != ENTRY_BLOCK_PTR
                        ? NEXT_INSN (BB_END (e->src)) : get_insns (),
                        NULL_RTX, e->src);
 
-  new_e = make_edge (new_bb, e->dest, EDGE_FALLTHRU);
+  /* ??? This info is likely going to be out of date very soon, but we must
+     create it to avoid getting an ICE later.  */
+  if (e->dest->il.rtl->global_live_at_start)
+    {
+      new_bb->il.rtl->global_live_at_start = ALLOC_REG_SET (&reg_obstack);
+      new_bb->il.rtl->global_live_at_end = ALLOC_REG_SET (&reg_obstack);
+      COPY_REG_SET (new_bb->il.rtl->global_live_at_start,
+                   e->dest->il.rtl->global_live_at_start);
+      COPY_REG_SET (new_bb->il.rtl->global_live_at_end,
+                   e->dest->il.rtl->global_live_at_start);
+    }
+
+  make_edge (new_bb, e->dest, EDGE_FALLTHRU);
   redirect_edge_and_branch_force (e, new_bb);
 
   return new_bb;
@@ -2805,11 +2861,11 @@ rtl_block_ends_with_call_p (basic_block bb)
 {
   rtx insn = BB_END (bb);
 
-  while (GET_CODE (insn) != CALL_INSN
+  while (!CALL_P (insn)
         && insn != BB_HEAD (bb)
         && keep_with_call_p (insn))
     insn = PREV_INSN (insn);
-  return (GET_CODE (insn) == CALL_INSN);
+  return (CALL_P (insn));
 }
 
 /* Return 1 if BB ends with a conditional branch, 0 otherwise.  */
@@ -2829,10 +2885,9 @@ need_fake_edge_p (rtx insn)
   if (!INSN_P (insn))
     return false;
 
-  if ((GET_CODE (insn) == CALL_INSN
+  if ((CALL_P (insn)
        && !SIBLING_CALL_P (insn)
        && !find_reg_note (insn, REG_NORETURN, NULL)
-       && !find_reg_note (insn, REG_ALWAYS_RETURN, NULL)
        && !CONST_OR_PURE_CALL_P (insn)))
     return true;
 
@@ -2860,7 +2915,7 @@ rtl_flow_call_edges_add (sbitmap blocks)
   int last_bb = last_basic_block;
   bool check_last_block = false;
 
-  if (n_basic_blocks == 0)
+  if (n_basic_blocks == NUM_FIXED_BLOCKS)
     return 0;
 
   if (! blocks)
@@ -2894,13 +2949,12 @@ rtl_flow_call_edges_add (sbitmap blocks)
        {
          edge e;
 
-         for (e = bb->succ; e; e = e->succ_next)
-           if (e->dest == EXIT_BLOCK_PTR)
-             {
-               insert_insn_on_edge (gen_rtx_USE (VOIDmode, const0_rtx), e);
-               commit_edge_insertions ();
-               break;
-             }
+         e = find_edge (bb, EXIT_BLOCK_PTR);
+         if (e)
+           {
+             insert_insn_on_edge (gen_rtx_USE (VOIDmode, const0_rtx), e);
+             commit_edge_insertions ();
+           }
        }
     }
 
@@ -2908,7 +2962,7 @@ rtl_flow_call_edges_add (sbitmap blocks)
      calls since there is no way that we can determine if they will
      return or not...  */
 
-  for (i = 0; i < last_bb; i++)
+  for (i = NUM_FIXED_BLOCKS; i < last_bb; i++)
     {
       basic_block bb = BASIC_BLOCK (i);
       rtx insn;
@@ -2930,7 +2984,7 @@ rtl_flow_call_edges_add (sbitmap blocks)
 
              /* Don't split the block between a call and an insn that should
                 remain in the same block as the call.  */
-             if (GET_CODE (insn) == CALL_INSN)
+             if (CALL_P (insn))
                while (split_at_insn != BB_END (bb)
                       && keep_with_call_p (NEXT_INSN (split_at_insn)))
                  split_at_insn = NEXT_INSN (split_at_insn);
@@ -2942,9 +2996,10 @@ rtl_flow_call_edges_add (sbitmap blocks)
 
 #ifdef ENABLE_CHECKING
              if (split_at_insn == BB_END (bb))
-               for (e = bb->succ; e; e = e->succ_next)
-                 if (e->dest == EXIT_BLOCK_PTR)
-                   abort ();
+               {
+                 e = find_edge (bb, EXIT_BLOCK_PTR);
+                 gcc_assert (e == NULL);
+               }
 #endif
 
              /* Note that the following may create a new basic block
@@ -2970,6 +3025,73 @@ rtl_flow_call_edges_add (sbitmap blocks)
   return blocks_split;
 }
 
+/* Add COMP_RTX as a condition at end of COND_BB.  FIRST_HEAD is
+   the conditional branch target, SECOND_HEAD should be the fall-thru
+   there is no need to handle this here the loop versioning code handles
+   this.  the reason for SECON_HEAD is that it is needed for condition
+   in trees, and this should be of the same type since it is a hook.  */
+static void
+rtl_lv_add_condition_to_bb (basic_block first_head ,
+                           basic_block second_head ATTRIBUTE_UNUSED, 
+                           basic_block cond_bb, void *comp_rtx)  
+{
+  rtx label, seq, jump;
+  rtx op0 = XEXP ((rtx)comp_rtx, 0);
+  rtx op1 = XEXP ((rtx)comp_rtx, 1);
+  enum rtx_code comp = GET_CODE ((rtx)comp_rtx);
+  enum machine_mode mode;
+
+
+  label = block_label (first_head);
+  mode = GET_MODE (op0);
+  if (mode == VOIDmode)
+    mode = GET_MODE (op1);
+
+  start_sequence ();
+  op0 = force_operand (op0, NULL_RTX);
+  op1 = force_operand (op1, NULL_RTX);
+  do_compare_rtx_and_jump (op0, op1, comp, 0,
+                          mode, NULL_RTX, NULL_RTX, label);
+  jump = get_last_insn ();
+  JUMP_LABEL (jump) = label;
+  LABEL_NUSES (label)++;
+  seq = get_insns ();
+  end_sequence ();
+
+  /* Add the new cond , in the new head.  */
+  emit_insn_after(seq, BB_END(cond_bb));
+}
+
+
+/* Given a block B with unconditional branch at its end, get the
+   store the return the branch edge and the fall-thru edge in
+   BRANCH_EDGE and FALLTHRU_EDGE respectively.  */
+static void
+rtl_extract_cond_bb_edges (basic_block b, edge *branch_edge,
+                          edge *fallthru_edge)
+{
+  edge e = EDGE_SUCC (b, 0);
+
+  if (e->flags & EDGE_FALLTHRU)
+    {
+      *fallthru_edge = e;
+      *branch_edge = EDGE_SUCC (b, 1);
+    }
+  else
+    {
+      *branch_edge = e;
+      *fallthru_edge = EDGE_SUCC (b, 1);
+    }
+}
+
+void
+init_rtl_bb_info (basic_block bb)
+{
+  gcc_assert (!bb->il.rtl);
+  bb->il.rtl = ggc_alloc_cleared (sizeof (struct rtl_bb_info));
+}
+
+
 /* Implementation of CFG manipulation for linearized RTL.  */
 struct cfg_hooks rtl_cfg_hooks = {
   "rtl",
@@ -2992,7 +3114,14 @@ struct cfg_hooks rtl_cfg_hooks = {
   rtl_tidy_fallthru_edge,
   rtl_block_ends_with_call_p,
   rtl_block_ends_with_condjump_p,
-  rtl_flow_call_edges_add
+  rtl_flow_call_edges_add,
+  NULL, /* execute_on_growing_pred */
+  NULL, /* execute_on_shrinking_pred */
+  NULL, /* duplicate loop for trees */
+  NULL, /* lv_add_condition_to_bb */
+  NULL, /* lv_adjust_loop_header_phi*/
+  NULL, /* extract_cond_bb_edges */
+  NULL                 /* flush_pending_stmts */
 };
 
 /* Implementation of CFG manipulation for cfg layout RTL, where
@@ -3028,6 +3157,13 @@ struct cfg_hooks cfg_layout_rtl_cfg_hooks = {
   NULL,
   rtl_block_ends_with_call_p,
   rtl_block_ends_with_condjump_p,
-  rtl_flow_call_edges_add
+  rtl_flow_call_edges_add,
+  NULL, /* execute_on_growing_pred */
+  NULL, /* execute_on_shrinking_pred */
+  duplicate_loop_to_header_edge, /* duplicate loop for trees */
+  rtl_lv_add_condition_to_bb, /* lv_add_condition_to_bb */
+  NULL, /* lv_adjust_loop_header_phi*/
+  rtl_extract_cond_bb_edges, /* extract_cond_bb_edges */
+  NULL                 /* flush_pending_stmts */  
 };