OSDN Git Service

2010-04-29 Brian Hackett <bhackett1024@gmail.com>
[pf3gnuchains/gcc-fork.git] / gcc / cfgrtl.c
index b269ba4..abdbf9d 100644 (file)
@@ -1,12 +1,13 @@
 /* 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, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   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, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* This file contains low level functions to manipulate the CFG and analyze it
    that are aware of the RTL intermediate language.
@@ -53,18 +53,18 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "toplev.h"
 #include "tm_p.h"
 #include "obstack.h"
+#include "insn-attr.h"
 #include "insn-config.h"
 #include "cfglayout.h"
 #include "expr.h"
 #include "target.h"
 #include "cfgloop.h"
 #include "ggc.h"
+#include "tree-pass.h"
+#include "df.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);
+static int can_delete_note_p (const_rtx);
+static int can_delete_label_p (const_rtx);
 static basic_block rtl_split_edge (edge);
 static bool rtl_move_block_after (basic_block, basic_block);
 static int rtl_verify_flow_info (void);
@@ -76,25 +76,32 @@ static void rtl_delete_block (basic_block);
 static basic_block rtl_redirect_edge_and_branch_force (edge, basic_block);
 static edge rtl_redirect_edge_and_branch (edge, basic_block);
 static basic_block rtl_split_block (basic_block, void *);
-static void rtl_dump_bb (basic_block, FILE *, int);
+static void rtl_dump_bb (basic_block, FILE *, int, int);
 static int rtl_verify_flow_info_1 (void);
-static void mark_killed_regs (rtx, rtx, void *);
 static void rtl_make_forwarder_block (edge);
 \f
 /* Return true if NOTE is not one of the ones that must be kept paired,
    so that we may simply delete it.  */
 
 static int
-can_delete_note_p (rtx note)
+can_delete_note_p (const_rtx note)
 {
-  return (NOTE_LINE_NUMBER (note) == NOTE_INSN_DELETED
-         || NOTE_LINE_NUMBER (note) == NOTE_INSN_BASIC_BLOCK);
+  switch (NOTE_KIND (note))
+    {
+    case NOTE_INSN_DELETED:
+    case NOTE_INSN_BASIC_BLOCK:
+    case NOTE_INSN_EPILOGUE_BEG:
+      return true;
+
+    default:
+      return false;
+    }
 }
 
 /* True if a given label can be deleted.  */
 
 static int
-can_delete_label_p (rtx label)
+can_delete_label_p (const_rtx label)
 {
   return (!LABEL_PRESERVE_P (label)
          /* User declared labels must be preserved.  */
@@ -114,15 +121,15 @@ delete_insn (rtx insn)
   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.
-         Convert them to the special NOTE_INSN_DELETED_LABEL note.  */
+        might be references via variables, constant pool etc.
+        Convert them to the special NOTE_INSN_DELETED_LABEL note.  */
       if (! can_delete_label_p (insn))
        {
          const char *name = LABEL_NAME (insn);
 
          really_delete = false;
          PUT_CODE (insn, NOTE);
-         NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED_LABEL;
+         NOTE_KIND (insn) = NOTE_INSN_DELETED_LABEL;
          NOTE_DELETED_LABEL_NAME (insn) = name;
        }
 
@@ -139,15 +146,15 @@ delete_insn (rtx insn)
 
   /* 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 (JUMP_P (insn)
-      && JUMP_LABEL (insn)
-      && LABEL_P (JUMP_LABEL (insn)))
-    LABEL_NUSES (JUMP_LABEL (insn))--;
-
-  /* Also if deleting an insn that references a label.  */
-  else
+  if (JUMP_P (insn))
     {
-      while ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)) != NULL_RTX
+      if (JUMP_LABEL (insn)
+         && LABEL_P (JUMP_LABEL (insn)))
+       LABEL_NUSES (JUMP_LABEL (insn))--;
+
+      /* If there are more targets, remove them too.  */
+      while ((note
+             = find_reg_note (insn, REG_LABEL_TARGET, NULL_RTX)) != NULL_RTX
             && LABEL_P (XEXP (note, 0)))
        {
          LABEL_NUSES (XEXP (note, 0))--;
@@ -155,9 +162,15 @@ delete_insn (rtx insn)
        }
     }
 
-  if (JUMP_P (insn)
-      && (GET_CODE (PATTERN (insn)) == ADDR_VEC
-         || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
+  /* Also if deleting any insn that references a label as an operand.  */
+  while ((note = find_reg_note (insn, REG_LABEL_OPERAND, NULL_RTX)) != NULL_RTX
+        && LABEL_P (XEXP (note, 0)))
+    {
+      LABEL_NUSES (XEXP (note, 0))--;
+      remove_note (insn, note);
+    }
+
+  if (JUMP_TABLE_DATA_P (insn))
     {
       rtx pat = PATTERN (insn);
       int diff_vec_p = GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC;
@@ -180,6 +193,7 @@ delete_insn (rtx insn)
 }
 
 /* Like delete_insn but also purge dead edges from BB.  */
+
 rtx
 delete_insn_and_edges (rtx insn)
 {
@@ -197,10 +211,11 @@ delete_insn_and_edges (rtx insn)
 }
 
 /* Unlink a chain of insns between START and FINISH, leaving notes
-   that must be paired.  */
+   that must be paired.  If CLEAR_BB is true, we set bb field for
+   insns that cannot be removed to NULL.  */
 
 void
-delete_insn_chain (rtx start, rtx finish)
+delete_insn_chain (rtx start, rtx finish, bool clear_bb)
 {
   rtx next;
 
@@ -215,26 +230,14 @@ delete_insn_chain (rtx start, rtx finish)
       else
        next = delete_insn (start);
 
+      if (clear_bb && !INSN_DELETED_P (start))
+       set_block_for_insn (start, NULL);
+
       if (start == finish)
        break;
       start = next;
     }
 }
-
-/* Like delete_insn but also purge dead edges from BB.  */
-void
-delete_insn_chain_and_edges (rtx first, rtx last)
-{
-  bool purge = false;
-
-  if (INSN_P (last)
-      && BLOCK_FOR_INSN (last)
-      && BB_END (BLOCK_FOR_INSN (last)) == last)
-    purge = true;
-  delete_insn_chain (first, last);
-  if (purge)
-    purge_dead_edges (BLOCK_FOR_INSN (last));
-}
 \f
 /* Create a new basic block consisting of the instructions between HEAD and END
    inclusive.  This function is designed to allow fast BB construction - reuses
@@ -304,7 +307,8 @@ create_basic_block_structure (rtx head, rtx end, rtx bb_note, basic_block after)
   bb->index = last_basic_block++;
   bb->flags = BB_NEW | BB_RTL;
   link_block (bb, after);
-  BASIC_BLOCK (bb->index) = bb;
+  SET_BASIC_BLOCK (bb->index, bb);
+  df_bb_refs_record (bb->index, false);
   update_bb_for_insn (bb);
   BB_SET_PARTITION (bb, BB_UNPARTITIONED);
 
@@ -323,14 +327,14 @@ create_basic_block_structure (rtx head, rtx end, rtx bb_note, basic_block after)
 static basic_block
 rtl_create_basic_block (void *headp, void *endp, basic_block after)
 {
-  rtx head = headp, end = endp;
+  rtx head = (rtx) headp, end = (rtx) endp;
   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 new_size = last_basic_block + (last_basic_block + 3) / 4;
-      VARRAY_GROW (basic_block_info, new_size);
+      VEC_safe_grow_cleared (basic_block, gc, basic_block_info, new_size);
     }
 
   n_basic_blocks++;
@@ -359,31 +363,23 @@ cfg_layout_create_basic_block (void *head, void *end, basic_block after)
 static void
 rtl_delete_block (basic_block b)
 {
-  rtx insn, end, tmp;
+  rtx insn, end;
 
   /* 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.  */
   insn = BB_HEAD (b);
-  if (LABEL_P (insn))
-    maybe_remove_eh_handler (insn);
 
-  /* Include any jump table following the basic block.  */
-  end = BB_END (b);
-  if (tablejump_p (end, NULL, &tmp))
-    end = tmp;
-
-  /* Include any barriers that may follow the basic block.  */
-  tmp = next_nonnote_insn (end);
-  while (tmp && BARRIER_P (tmp))
-    {
-      end = tmp;
-      tmp = next_nonnote_insn (end);
-    }
+  end = get_last_bb_insn (b);
 
   /* Selectively delete the entire chain.  */
   BB_HEAD (b) = NULL;
-  delete_insn_chain (insn, end);
+  delete_insn_chain (insn, end, true);
+
+
+  if (dump_file)
+    fprintf (dump_file, "deleting block %d\n", b->index);
+  df_bb_delete (b->index);
 }
 \f
 /* Records the basic block struct in BLOCK_FOR_INSN for every insn.  */
@@ -409,38 +405,116 @@ compute_bb_for_insn (void)
 
 /* Release the basic_block_for_insn array.  */
 
-void
+unsigned int
 free_bb_for_insn (void)
 {
   rtx insn;
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
     if (!BARRIER_P (insn))
       BLOCK_FOR_INSN (insn) = NULL;
+  return 0;
+}
+
+static unsigned int
+rest_of_pass_free_cfg (void)
+{
+#ifdef DELAY_SLOTS
+  /* The resource.c machinery uses DF but the CFG isn't guaranteed to be
+     valid at that point so it would be too late to call df_analyze.  */
+  if (optimize > 0 && flag_delayed_branch)
+    df_analyze ();
+#endif
+
+  free_bb_for_insn ();
+  return 0;
 }
 
+struct rtl_opt_pass pass_free_cfg =
+{
+ {
+  RTL_PASS,
+  "*free_cfg",                          /* name */
+  NULL,                                 /* gate */
+  rest_of_pass_free_cfg,                /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_NONE,                              /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  PROP_cfg,                             /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  0,                                    /* todo_flags_finish */
+ }
+};
+
 /* 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 ());
+}
+
+/* Emit INSN at the entry point of the function, ensuring that it is only
+   executed once per function.  */
+void
+emit_insn_at_entry (rtx insn)
+{
+  edge_iterator ei = ei_start (ENTRY_BLOCK_PTR->succs);
+  edge e = ei_safe_edge (ei);
+  gcc_assert (e->flags & EDGE_FALLTHRU);
+
+  insert_insn_on_edge (insn, e);
+  commit_edge_insertions ();
+}
+
+/* Update BLOCK_FOR_INSN of insns between BEGIN and END
+   (or BARRIER if found) and notify df of the bb change.
+   The insn chain range is inclusive
+   (i.e. both BEGIN and END will be updated. */
+
+static void
+update_bb_for_insn_chain (rtx begin, rtx end, basic_block bb)
+{
+  rtx insn;
+
+  end = NEXT_INSN (end);
+  for (insn = begin; insn != end; insn = NEXT_INSN (insn))
+    if (!BARRIER_P (insn))
+      df_insn_change_bb (insn, bb);
 }
 
-/* Update insns block within BB.  */
+/* Update BLOCK_FOR_INSN of insns in BB to BB,
+   and notify df of the change.  */
 
 void
 update_bb_for_insn (basic_block bb)
 {
+  update_bb_for_insn_chain (BB_HEAD (bb), BB_END (bb), bb);
+}
+
+\f
+/* Return the INSN immediately following the NOTE_INSN_BASIC_BLOCK
+   note associated with the BLOCK.  */
+
+static rtx
+first_insn_after_basic_block_note (basic_block block)
+{
   rtx insn;
 
-  for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
-    {
-      if (!BARRIER_P (insn))
-       set_block_for_insn (insn, bb);
-      if (insn == BB_END (bb))
-       break;
-    }
+  /* Get the first instruction in the block.  */
+  insn = BB_HEAD (block);
+
+  if (insn == NULL_RTX)
+    return NULL_RTX;
+  if (LABEL_P (insn))
+    insn = NEXT_INSN (insn);
+  gcc_assert (NOTE_INSN_BASIC_BLOCK_P (insn));
+
+  return NEXT_INSN (insn);
 }
-\f
+
 /* Creates a new basic block just after basic block B by splitting
    everything after specified instruction I.  */
 
@@ -448,7 +522,7 @@ static basic_block
 rtl_split_block (basic_block bb, void *insnp)
 {
   basic_block new_bb;
-  rtx insn = insnp;
+  rtx insn = (rtx) insnp;
   edge e;
   edge_iterator ei;
 
@@ -457,7 +531,26 @@ rtl_split_block (basic_block bb, void *insnp)
       insn = first_insn_after_basic_block_note (bb);
 
       if (insn)
-       insn = PREV_INSN (insn);
+       {
+         rtx next = insn;
+
+         insn = PREV_INSN (insn);
+
+         /* If the block contains only debug insns, insn would have
+            been NULL in a non-debug compilation, and then we'd end
+            up emitting a DELETED note.  For -fcompare-debug
+            stability, emit the note too.  */
+         if (insn != BB_END (bb)
+             && DEBUG_INSN_P (next)
+             && DEBUG_INSN_P (BB_END (bb)))
+           {
+             while (next != BB_END (bb) && DEBUG_INSN_P (next))
+               next = NEXT_INSN (next);
+
+             if (next == BB_END (bb))
+               emit_note_after (NOTE_INSN_DELETED, next);
+           }
+       }
       else
        insn = get_last_insn ();
     }
@@ -479,32 +572,8 @@ rtl_split_block (basic_block bb, void *insnp)
   FOR_EACH_EDGE (e, ei, new_bb->succs)
     e->src = new_bb;
 
-  if (bb->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_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->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.  */
-      if (reload_completed)
-       {
-         bb->flags |= BB_DIRTY;
-         new_bb->flags |= BB_DIRTY;
-       }
-#endif
-    }
-
+  /* The new block starts off being dirty.  */
+  df_set_bb_dirty (bb);
   return new_bb;
 }
 
@@ -516,8 +585,15 @@ rtl_merge_blocks (basic_block a, basic_block b)
 {
   rtx b_head = BB_HEAD (b), b_end = BB_END (b), a_end = BB_END (a);
   rtx del_first = NULL_RTX, del_last = NULL_RTX;
+  rtx b_debug_start = b_end, b_debug_end = b_end;
   int b_empty = 0;
 
+  if (dump_file)
+    fprintf (dump_file, "merging block %d into block %d\n", b->index, a->index);
+
+  while (DEBUG_INSN_P (b_end))
+    b_end = PREV_INSN (b_debug_start = b_end);
+
   /* If there was a CODE_LABEL beginning B, delete it.  */
   if (LABEL_P (b_head))
     {
@@ -550,7 +626,7 @@ rtl_merge_blocks (basic_block a, basic_block b)
 
       for (prev = PREV_INSN (a_end); ; prev = PREV_INSN (prev))
        if (!NOTE_P (prev)
-           || NOTE_LINE_NUMBER (prev) == NOTE_INSN_BASIC_BLOCK
+           || NOTE_INSN_BASIC_BLOCK_P (prev)
            || prev == BB_HEAD (a))
          break;
 
@@ -578,37 +654,46 @@ rtl_merge_blocks (basic_block a, basic_block b)
   /* Delete everything marked above as well as crap that might be
      hanging out between the two blocks.  */
   BB_HEAD (b) = NULL;
-  delete_insn_chain (del_first, del_last);
+  delete_insn_chain (del_first, del_last, true);
 
   /* Reassociate the insns of B with A.  */
   if (!b_empty)
     {
-      rtx x;
-
-      for (x = a_end; x != b_end; x = NEXT_INSN (x))
-       set_block_for_insn (x, a);
+      update_bb_for_insn_chain (a_end, b_debug_end, a);
 
-      set_block_for_insn (b_end, a);
-
-      a_end = b_end;
+      a_end = b_debug_end;
+    }
+  else if (b_end != b_debug_end)
+    {
+      /* Move any deleted labels and other notes between the end of A
+        and the debug insns that make up B after the debug insns,
+        bringing the debug insns into A while keeping the notes after
+        the end of A.  */
+      if (NEXT_INSN (a_end) != b_debug_start)
+       reorder_insns_nobb (NEXT_INSN (a_end), PREV_INSN (b_debug_start),
+                           b_debug_end);
+      update_bb_for_insn_chain (b_debug_start, b_debug_end, a);
+      a_end = b_debug_end;
     }
 
+  df_bb_delete (b->index);
   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)
+rtl_can_merge_blocks (basic_block a, basic_block b)
 {
   /* 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.
 
      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 
+     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))
@@ -665,11 +750,11 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
      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 
+     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 (find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)
       || BB_PARTITION (src) != BB_PARTITION (target))
     return NULL;
@@ -698,7 +783,8 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
      the cc0 setter too.  */
   kill_from = insn;
 #ifdef HAVE_cc0
-  if (reg_mentioned_p (cc0_rtx, PATTERN (insn)))
+  if (reg_mentioned_p (cc0_rtx, PATTERN (insn))
+      && only_sets_cc0_p (PREV_INSN (insn)))
     kill_from = PREV_INSN (insn);
 #endif
 
@@ -714,7 +800,7 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
        {
          rtx insn = src->il.rtl->footer;
 
-          delete_insn_chain (kill_from, BB_END (src));
+         delete_insn_chain (kill_from, BB_END (src), false);
 
          /* Remove barriers but keep jumptables.  */
          while (insn)
@@ -734,7 +820,8 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
            }
        }
       else
-        delete_insn_chain (kill_from, PREV_INSN (BB_HEAD (target)));
+       delete_insn_chain (kill_from, PREV_INSN (BB_HEAD (target)),
+                          false);
     }
 
   /* If this already is simplejump, redirect it.  */
@@ -770,13 +857,13 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
                 INSN_UID (insn), INSN_UID (BB_END (src)));
 
 
-      delete_insn_chain (kill_from, insn);
+      delete_insn_chain (kill_from, insn, false);
 
       /* Recognize a tablejump that we are converting to a
         simple jump and remove its associated CODE_LABEL
         and ADDR_VEC or ADDR_DIFF_VEC.  */
       if (tablejump_p (insn, &label, &table))
-       delete_insn_chain (label, table);
+       delete_insn_chain (label, table, false);
 
       barrier = next_nonnote_insn (BB_END (src));
       if (!barrier || !BARRIER_P (barrier))
@@ -789,11 +876,9 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
                 which originally were or were created before jump table are
                 inside the basic block.  */
              rtx new_insn = BB_END (src);
-             rtx tmp;
 
-             for (tmp = NEXT_INSN (BB_END (src)); tmp != barrier;
-                  tmp = NEXT_INSN (tmp))
-               set_block_for_insn (tmp, src);
+             update_bb_for_insn_chain (NEXT_INSN (BB_END (src)),
+                                       PREV_INSN (barrier), src);
 
              NEXT_INSN (PREV_INSN (new_insn)) = NEXT_INSN (new_insn);
              PREV_INSN (NEXT_INSN (new_insn)) = PREV_INSN (new_insn);
@@ -821,65 +906,30 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
   e->probability = REG_BR_PROB_BASE;
   e->count = src->count;
 
-  /* 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 (NOTE_P (BB_END (e->src))
-        && NOTE_LINE_NUMBER (BB_END (e->src)) >= 0)
-    delete_insn (BB_END (e->src));
-
   if (e->dest != target)
     redirect_edge_succ (e, target);
-
   return e;
 }
 
-/* Return last loop_beg note appearing after INSN, before start of next
-   basic block.  Return INSN if there are no such notes.
-
-   When emitting jump to redirect a fallthru edge, it should always appear
-   after the LOOP_BEG notes, as loop optimizer expect loop to either start by
-   fallthru edge or jump following the LOOP_BEG note jumping to the loop exit
-   test.  */
-
-static rtx
-last_loop_beg_note (rtx insn)
-{
-  rtx last = insn;
-
-  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)
-      last = insn;
+/* Subroutine of redirect_branch_edge that tries to patch the jump
+   instruction INSN so that it reaches block NEW.  Do this
+   only when it originally reached block OLD.  Return true if this
+   worked or the original target wasn't OLD, return false if redirection
+   doesn't work.  */
 
-  return last;
-}
-
-/* Redirect edge representing branch of (un)conditional jump or tablejump,
-   NULL on failure  */
-static edge
-redirect_branch_edge (edge e, basic_block target)
+static bool
+patch_jump_insn (rtx insn, rtx old_label, basic_block new_bb)
 {
   rtx tmp;
-  rtx old_label = BB_HEAD (e->dest);
-  basic_block src = e->src;
-  rtx insn = BB_END (src);
-
-  /* We can only redirect non-fallthru edges of jump insn.  */
-  if (e->flags & EDGE_FALLTHRU)
-    return NULL;
-  else if (!JUMP_P (insn))
-    return NULL;
-
   /* Recognize a tablejump and adjust all matching cases.  */
   if (tablejump_p (insn, NULL, &tmp))
     {
       rtvec vec;
       int j;
-      rtx new_label = block_label (target);
+      rtx new_label = block_label (new_bb);
 
-      if (target == EXIT_BLOCK_PTR)
-       return NULL;
+      if (new_bb == EXIT_BLOCK_PTR)
+       return false;
       if (GET_CODE (PATTERN (tmp)) == ADDR_VEC)
        vec = XVEC (PATTERN (tmp), 0);
       else
@@ -906,6 +956,48 @@ redirect_branch_edge (edge e, basic_block target)
          ++LABEL_NUSES (new_label);
        }
     }
+  else if ((tmp = extract_asm_operands (PATTERN (insn))) != NULL)
+    {
+      int i, n = ASM_OPERANDS_LABEL_LENGTH (tmp);
+      rtx new_label, note;
+
+      if (new_bb == EXIT_BLOCK_PTR)
+       return false;
+      new_label = block_label (new_bb);
+
+      for (i = 0; i < n; ++i)
+       {
+         rtx old_ref = ASM_OPERANDS_LABEL (tmp, i);
+         gcc_assert (GET_CODE (old_ref) == LABEL_REF);
+         if (XEXP (old_ref, 0) == old_label)
+           {
+             ASM_OPERANDS_LABEL (tmp, i)
+               = gen_rtx_LABEL_REF (Pmode, new_label);
+             --LABEL_NUSES (old_label);
+             ++LABEL_NUSES (new_label);
+           }
+       }
+
+      if (JUMP_LABEL (insn) == old_label)
+       {
+         JUMP_LABEL (insn) = new_label;
+         note = find_reg_note (insn, REG_LABEL_TARGET, new_label);
+         if (note)
+           remove_note (insn, note);
+       }
+      else
+       {
+         note = find_reg_note (insn, REG_LABEL_TARGET, old_label);
+         if (note)
+           remove_note (insn, note);
+         if (JUMP_LABEL (insn) != new_label
+             && !find_reg_note (insn, REG_LABEL_TARGET, new_label))
+           add_reg_note (insn, REG_LABEL_TARGET, new_label);
+       }
+      while ((note = find_reg_note (insn, REG_LABEL_OPERAND, old_label))
+            != NULL_RTX)
+       XEXP (note, 0) = new_label;
+    }
   else
     {
       /* ?? We may play the games with moving the named labels from
@@ -914,20 +1006,55 @@ redirect_branch_edge (edge e, basic_block target)
       if (computed_jump_p (insn)
          /* A return instruction can't be redirected.  */
          || returnjump_p (insn))
-       return NULL;
-
-      /* If the insn doesn't go where we think, we're confused.  */
-      gcc_assert (JUMP_LABEL (insn) == old_label);
+       return false;
 
-      /* 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 (!currently_expanding_to_rtl || JUMP_LABEL (insn) == old_label)
        {
-         gcc_assert (target == EXIT_BLOCK_PTR);
-         return NULL;
+         /* If the insn doesn't go where we think, we're confused.  */
+         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 (new_bb), 0))
+           {
+             gcc_assert (new_bb == EXIT_BLOCK_PTR);
+             return false;
+           }
        }
     }
+  return true;
+}
+
+
+/* Redirect edge representing branch of (un)conditional jump or tablejump,
+   NULL on failure  */
+static edge
+redirect_branch_edge (edge e, basic_block target)
+{
+  rtx old_label = BB_HEAD (e->dest);
+  basic_block src = e->src;
+  rtx insn = BB_END (src);
+
+  /* We can only redirect non-fallthru edges of jump insn.  */
+  if (e->flags & EDGE_FALLTHRU)
+    return NULL;
+  else if (!JUMP_P (insn) && !currently_expanding_to_rtl)
+    return NULL;
+
+  if (!currently_expanding_to_rtl)
+    {
+      if (!patch_jump_insn (insn, old_label, target))
+       return NULL;
+    }
+  else
+    /* When expanding this BB might actually contain multiple
+       jumps (i.e. not yet split by find_many_sub_basic_blocks).
+       Redirect all of those that match our label.  */
+    for (insn = BB_HEAD (src); insn != NEXT_INSN (BB_END (src));
+        insn = NEXT_INSN (insn))
+      if (JUMP_P (insn) && !patch_jump_insn (insn, old_label, target))
+       return NULL;
 
   if (dump_file)
     fprintf (dump_file, "Edge %i->%i redirected to %i\n",
@@ -935,6 +1062,7 @@ redirect_branch_edge (edge e, basic_block target)
 
   if (e->dest != target)
     e = redirect_edge_succ_nodup (e, target);
+
   return e;
 }
 
@@ -963,7 +1091,7 @@ rtl_redirect_edge_and_branch (edge e, basic_block target)
 
   if ((ret = try_redirect_by_replacing_jump (e, target, false)) != NULL)
     {
-      src->flags |= BB_DIRTY;
+      df_set_bb_dirty (src);
       return ret;
     }
 
@@ -971,7 +1099,7 @@ rtl_redirect_edge_and_branch (edge e, basic_block target)
   if (!ret)
     return NULL;
 
-  src->flags |= BB_DIRTY;
+  df_set_bb_dirty (src);
   return ret;
 }
 
@@ -985,15 +1113,13 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
   rtx note;
   edge new_edge;
   int abnormal_edge_flags = 0;
+  int loc;
 
   /* In the case the last instruction is conditional jump to the next
      instruction, first redirect the jump itself and then continue
      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;
@@ -1002,7 +1128,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
 
       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)
        {
@@ -1041,9 +1167,9 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
          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;
@@ -1058,9 +1184,9 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
              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);
        }
@@ -1075,9 +1201,6 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
         forward from the last instruction of the old block.  */
       if (!tablejump_p (BB_END (e->src), NULL, &note))
        note = BB_END (e->src);
-
-      /* Position the new block correctly relative to loop notes.  */
-      note = last_loop_beg_note (note);
       note = NEXT_INSN (note);
 
       jump_block = create_basic_block (note, NULL, e->src);
@@ -1085,16 +1208,6 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
       jump_block->frequency = EDGE_FREQUENCY (e);
       jump_block->loop_depth = target->loop_depth;
 
-      if (target->il.rtl->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.  */
 
       BB_COPY_PARTITION (jump_block, e->src);
@@ -1103,12 +1216,8 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
          && 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)));
-      
+       add_reg_note (BB_END (jump_block), REG_CROSSING_JUMP, NULL_RTX);
+
       /* Wire edge in.  */
       new_edge = make_edge (e->src, jump_block, EDGE_FALLTHRU);
       new_edge->probability = e->probability;
@@ -1123,11 +1232,15 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
   else
     jump_block = e->src;
 
+  if (e->goto_locus && e->goto_block == NULL)
+    loc = e->goto_locus;
+  else
+    loc = 0;
   e->flags &= ~EDGE_FALLTHRU;
   if (target == EXIT_BLOCK_PTR)
     {
 #ifdef HAVE_return
-       emit_jump_insn_after_noloc (gen_return (), BB_END (jump_block));
+       emit_jump_insn_after_setloc (gen_return (), BB_END (jump_block), loc);
 #else
        gcc_unreachable ();
 #endif
@@ -1135,7 +1248,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
   else
     {
       rtx label = block_label (target);
-      emit_jump_insn_after_noloc (gen_jump (label), BB_END (jump_block));
+      emit_jump_insn_after_setloc (gen_jump (label), BB_END (jump_block), loc);
       JUMP_LABEL (BB_END (jump_block)) = label;
       LABEL_NUSES (label)++;
     }
@@ -1146,6 +1259,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
   if (abnormal_edge_flags)
     make_edge (src, target, abnormal_edge_flags);
 
+  df_mark_solutions_dirty ();
   return new_bb;
 }
 
@@ -1172,6 +1286,7 @@ rtl_redirect_edge_and_branch_force (edge e, basic_block target)
 
   /* In case the edge redirection failed, try to force it to be non-fallthru
      and redirect newly created simplejump.  */
+  df_set_bb_dirty (e->src);
   return force_nonfallthru_and_redirect (e, target);
 }
 
@@ -1215,54 +1330,15 @@ rtl_tidy_fallthru_edge (edge e)
 #endif
 
       q = PREV_INSN (q);
-
-      /* 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 (NOTE_P (q) && NOTE_LINE_NUMBER (q) >= 0)
-       q = PREV_INSN (q);
     }
 
   /* Selectively unlink the sequence.  */
   if (q != PREV_INSN (BB_HEAD (c)))
-    delete_insn_chain (NEXT_INSN (q), PREV_INSN (BB_HEAD (c)));
+    delete_insn_chain (NEXT_INSN (q), PREV_INSN (BB_HEAD (c)), false);
 
   e->flags |= EDGE_FALLTHRU;
 }
 \f
-/* Helper function for split_edge.  Return true in case edge BB2 to BB1
-   is back edge of syntactic loop.  */
-
-static bool
-back_edge_of_syntactic_loop_p (basic_block bb1, basic_block bb2)
-{
-  rtx insn;
-  int count = 0;
-  basic_block bb;
-
-  if (bb1 == bb2)
-    return true;
-
-  /* ??? Could we guarantee that bb indices are monotone, so that we could
-     just compare them?  */
-  for (bb = bb1; bb && bb != bb2; bb = bb->next_bb)
-    continue;
-
-  if (!bb)
-    return false;
-
-  for (insn = BB_END (bb1); insn != BB_HEAD (bb2) && count >= 0;
-       insn = NEXT_INSN (insn))
-    if (NOTE_P (insn))
-      {
-       if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
-         count++;
-       else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
-         count--;
-      }
-
-  return count >= 0;
-}
-
 /* Should move basic block BB after basic block AFTER.  NIY.  */
 
 static bool
@@ -1303,32 +1379,8 @@ rtl_split_edge (edge edge_in)
        force_nonfallthru (e);
     }
 
-  /* Create the basic block note.
-
-     Where we place the note can have a noticeable impact on the generated
-     code.  Consider this cfg:
-
-                       E
-                       |
-                       0
-                      / \
-                  +->1-->2--->E
-                   |  |
-                  +--+
-
-      If we need to insert an insn on the edge from block 0 to block 1,
-      we want to ensure the instructions we insert are outside of any
-      loop notes that physically sit between block 0 and block 1.  Otherwise
-      we confuse the loop optimizer into thinking the loop is a phony.  */
-
-  if (edge_in->dest != EXIT_BLOCK_PTR
-      && PREV_INSN (BB_HEAD (edge_in->dest))
-      && 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))
-    before = PREV_INSN (BB_HEAD (edge_in->dest));
-  else if (edge_in->dest != EXIT_BLOCK_PTR)
+  /* Create the basic block note.  */
+  if (edge_in->dest != EXIT_BLOCK_PTR)
     before = BB_HEAD (edge_in->dest);
   else
     before = NULL_RTX;
@@ -1338,10 +1390,6 @@ rtl_split_edge (edge edge_in)
   if (edge_in->flags & EDGE_FALLTHRU && edge_in->dest == EXIT_BLOCK_PTR)
     {
       before = NEXT_INSN (BB_END (edge_in->src));
-      if (before
-         && 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);
     }
@@ -1352,17 +1400,6 @@ rtl_split_edge (edge edge_in)
       BB_COPY_PARTITION (bb, edge_in->dest);
     }
 
-  /* ??? This info is likely going to be out of date very soon.  */
-  if (edge_in->dest->il.rtl->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);
 
   /* For non-fallthru edges, we must adjust the predecessor's
@@ -1373,7 +1410,22 @@ rtl_split_edge (edge edge_in)
       gcc_assert (redirected);
     }
   else
-    redirect_edge_succ (edge_in, bb);
+    {
+      if (edge_in->src != ENTRY_BLOCK_PTR)
+       {
+         /* For asm goto even splitting of fallthru edge might
+            need insn patching, as other labels might point to the
+            old label.  */
+         rtx last = BB_END (edge_in->src);
+         if (last
+             && JUMP_P (last)
+             && edge_in->dest != EXIT_BLOCK_PTR
+             && extract_asm_operands (PATTERN (last)) != NULL_RTX
+             && patch_jump_insn (last, before, bb))
+           df_set_bb_dirty (edge_in->src);
+       }
+      redirect_edge_succ (edge_in, bb);
+    }
 
   return bb;
 }
@@ -1400,118 +1452,10 @@ insert_insn_on_edge (rtx pattern, edge e)
   end_sequence ();
 }
 
-/* Called from safe_insert_insn_on_edge through note_stores, marks live
-   registers that are killed by the store.  */
-static void
-mark_killed_regs (rtx reg, rtx set ATTRIBUTE_UNUSED, void *data)
-{
-  regset killed = data;
-  int regno, i;
-
-  if (GET_CODE (reg) == SUBREG)
-    reg = SUBREG_REG (reg);
-  if (!REG_P (reg))
-    return;
-  regno = REGNO (reg);
-  if (regno >= FIRST_PSEUDO_REGISTER)
-    SET_REGNO_REG_SET (killed, regno);
-  else
-    {
-      for (i = 0; i < (int) hard_regno_nregs[regno][GET_MODE (reg)]; i++)
-       SET_REGNO_REG_SET (killed, regno + i);
-    }
-}
-
-/* Similar to insert_insn_on_edge, tries to put INSN to edge E.  Additionally
-   it checks whether this will not clobber the registers that are live on the
-   edge (i.e. it requires liveness information to be up-to-date) and if there
-   are some, then it tries to save and restore them.  Returns true if
-   successful.  */
-bool
-safe_insert_insn_on_edge (rtx insn, edge e)
-{
-  rtx x;
-  regset killed;
-  rtx save_regs = NULL_RTX;
-  unsigned regno;
-  int noccmode;
-  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);
-
-  /* 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]
-             : GET_MODE (regno_reg_rtx[regno]);
-      if (mode == VOIDmode)
-       return false;
-
-      if (noccmode && mode == CCmode)
-       return false;
-       
-      save_regs = alloc_EXPR_LIST (0,
-                                  alloc_EXPR_LIST (0,
-                                                   gen_reg_rtx (mode),
-                                                   gen_raw_REG (mode, regno)),
-                                  save_regs);
-    }
-
-  if (save_regs)
-    {
-      rtx from, to;
-
-      start_sequence ();
-      for (x = save_regs; x; x = XEXP (x, 1))
-       {
-         from = XEXP (XEXP (x, 0), 1);
-         to = XEXP (XEXP (x, 0), 0);
-         emit_move_insn (to, from);
-       }
-      emit_insn (insn);
-      for (x = save_regs; x; x = XEXP (x, 1))
-       {
-         from = XEXP (XEXP (x, 0), 0);
-         to = XEXP (XEXP (x, 0), 1);
-         emit_move_insn (to, from);
-       }
-      insn = get_insns ();
-      end_sequence ();
-      free_EXPR_LIST_list (&save_regs);
-    }
-  insert_insn_on_edge (insn, e);
-  
-  FREE_REG_SET (killed);
-
-  return true;
-}
-
 /* Update the CFG for the instructions queued on edge E.  */
 
-static void
-commit_one_edge_insertion (edge e, int watch_calls)
+void
+commit_one_edge_insertion (edge e)
 {
   rtx before = NULL_RTX, after = NULL_RTX, insns, tmp, last;
   basic_block bb = NULL;
@@ -1520,29 +1464,10 @@ commit_one_edge_insertion (edge e, int watch_calls)
   insns = e->insns.r;
   e->insns.r = NULL_RTX;
 
-  /* Special case -- avoid inserting code between call and storing
-     its return value.  */
-  if (watch_calls && (e->flags & EDGE_FALLTHRU)
-      && single_pred_p (e->dest)
-      && e->src != ENTRY_BLOCK_PTR
-      && CALL_P (BB_END (e->src)))
-    {
-      rtx next = next_nonnote_insn (BB_END (e->src));
-
-      after = BB_HEAD (e->dest);
-      /* The first insn after the call may be a stack pop, skip it.  */
-      while (next
-            && keep_with_call_p (next))
-       {
-         after = next;
-         next = next_nonnote_insn (next);
-       }
-      bb = e->dest;
-    }
   if (!before && !after)
     {
       /* Figure out where to put these things.  If the destination has
-         one predecessor, insert there.  Except for the exit block.  */
+        one predecessor, insert there.  Except for the exit block.  */
       if (single_pred_p (e->dest) && e->dest != EXIT_BLOCK_PTR)
        {
          bb = e->dest;
@@ -1563,7 +1488,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.  */
+        insert there.  Except for the entry block.  */
       else if ((e->flags & EDGE_ABNORMAL) == 0
               && single_succ_p (e->src)
               && e->src != ENTRY_BLOCK_PTR)
@@ -1577,11 +1502,7 @@ 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 (JUMP_P (BB_END (bb)))
-           for (before = BB_END (bb);
-                NOTE_P (PREV_INSN (before))
-                && NOTE_LINE_NUMBER (PREV_INSN (before)) ==
-                NOTE_INSN_LOOP_BEG; before = PREV_INSN (before))
-             ;
+           before = BB_END (bb);
          else
            {
              /* We'd better be fallthru, or we've lost track of
@@ -1601,26 +1522,11 @@ commit_one_edge_insertion (edge e, int watch_calls)
              && targetm.have_named_sections
              && e->src != ENTRY_BLOCK_PTR
              && BB_PARTITION (e->src) == BB_COLD_PARTITION
-             && !(e->flags & EDGE_CROSSING))
-           {
-             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 (NOTE_P (cur_insn)
-                   && NOTE_LINE_NUMBER (cur_insn) == NOTE_INSN_BASIC_BLOCK)
-                 {
-                   bb_note = cur_insn;
-                   break;
-                 }
-
-             if (JUMP_P (BB_END (bb))
-                 && !any_condjump_p (BB_END (bb))
-                 && (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)));
-           }
+             && !(e->flags & EDGE_CROSSING)
+             && JUMP_P (after)
+             && !any_condjump_p (after)
+             && (single_succ_edge (bb)->flags & EDGE_CROSSING))
+           add_reg_note (after, REG_CROSSING_JUMP, NULL_RTX);
        }
     }
 
@@ -1628,18 +1534,18 @@ commit_one_edge_insertion (edge e, int watch_calls)
 
   if (before)
     {
-      emit_insn_before_noloc (insns, before);
+      emit_insn_before_noloc (insns, before, bb);
       last = prev_nonnote_insn (before);
     }
   else
-    last = emit_insn_after_noloc (insns, after);
+    last = emit_insn_after_noloc (insns, after, bb);
 
   if (returnjump_p (last))
     {
       /* ??? Remove all outgoing edges from BB and add one for EXIT.
-         This is not currently a problem because this only happens
-         for the (single) epilogue, which already has a fallthru edge
-         to EXIT.  */
+        This is not currently a problem because this only happens
+        for the (single) epilogue, which already has a fallthru edge
+        to EXIT.  */
 
       e = single_succ_edge (bb);
       gcc_assert (e->dest == EXIT_BLOCK_PTR
@@ -1655,7 +1561,8 @@ commit_one_edge_insertion (edge e, int watch_calls)
     gcc_assert (!JUMP_P (last));
 
   /* Mark the basic block for find_many_sub_basic_blocks.  */
-  bb->aux = &bb->aux;
+  if (current_ir_type () != IR_RTL_CFGLAYOUT)
+    bb->aux = &bb->aux;
 }
 
 /* Update the CFG for all queued instructions.  */
@@ -1680,56 +1587,18 @@ commit_edge_insertions (void)
        if (e->insns.r)
          {
            changed = true;
-           commit_one_edge_insertion (e, false);
+           commit_one_edge_insertion (e);
          }
     }
 
   if (!changed)
     return;
 
-  blocks = sbitmap_alloc (last_basic_block);
-  sbitmap_zero (blocks);
-  FOR_EACH_BB (bb)
-    if (bb->aux)
-      {
-        SET_BIT (blocks, bb->index);
-       /* Check for forgotten bb->aux values before commit_edge_insertions
-          call.  */
-       gcc_assert (bb->aux == &bb->aux);
-       bb->aux = NULL;
-      }
-  find_many_sub_basic_blocks (blocks);
-  sbitmap_free (blocks);
-}
-\f
-/* Update the CFG for all queued instructions, taking special care of inserting
-   code on edges between call and storing its return value.  */
-
-void
-commit_edge_insertions_watch_calls (void)
-{
-  basic_block bb;
-  sbitmap blocks;
-  bool changed = false;
-
-#ifdef ENABLE_CHECKING
-  verify_flow_info ();
-#endif
-
-  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
-    {
-      edge e;
-      edge_iterator ei;
-
-      FOR_EACH_EDGE (e, ei, bb->succs)
-       if (e->insns.r)
-         {
-           changed = true;
-           commit_one_edge_insertion (e, true);
-         }
-    }
-
-  if (!changed)
+  /* In the old rtl CFG API, it was OK to insert control flow on an
+     edge, apparently?  In cfglayout mode, this will *not* work, and
+     the caller is responsible for making sure that control flow is
+     valid at all times.  */
+  if (current_ir_type () == IR_RTL_CFGLAYOUT)
     return;
 
   blocks = sbitmap_alloc (last_basic_block);
@@ -1737,7 +1606,7 @@ commit_edge_insertions_watch_calls (void)
   FOR_EACH_BB (bb)
     if (bb->aux)
       {
-        SET_BIT (blocks, bb->index);
+       SET_BIT (blocks, bb->index);
        /* Check for forgotten bb->aux values before commit_edge_insertions
           call.  */
        gcc_assert (bb->aux == &bb->aux);
@@ -1747,53 +1616,61 @@ commit_edge_insertions_watch_calls (void)
   sbitmap_free (blocks);
 }
 \f
+
 /* Print out RTL-specific basic block information (live information
    at start and end).  */
 
 static void
-rtl_dump_bb (basic_block bb, FILE *outf, int indent)
+rtl_dump_bb (basic_block bb, FILE *outf, int indent, int flags ATTRIBUTE_UNUSED)
 {
   rtx insn;
   rtx last;
   char *s_indent;
 
-  s_indent = alloca ((size_t) indent + 1);
+  s_indent = (char *) alloca ((size_t) indent + 1);
   memset (s_indent, ' ', (size_t) indent);
   s_indent[indent] = '\0';
 
-  fprintf (outf, ";;%s Registers live at start: ", s_indent);
-  dump_regset (bb->il.rtl->global_live_at_start, outf);
-  putc ('\n', outf);
+  if (df)
+    {
+      df_dump_top (bb, outf);
+      putc ('\n', outf);
+    }
 
   for (insn = BB_HEAD (bb), last = NEXT_INSN (BB_END (bb)); insn != last;
        insn = NEXT_INSN (insn))
     print_rtl_single (outf, insn);
 
-  fprintf (outf, ";;%s Registers live at end: ", s_indent);
-  dump_regset (bb->il.rtl->global_live_at_end, outf);
-  putc ('\n', outf);
+  if (df)
+    {
+      df_dump_bottom (bb, outf);
+      putc ('\n', outf);
+    }
+
 }
 \f
 /* Like print_rtl, but also print out live information for the start of each
    basic block.  */
 
 void
-print_rtl_with_bb (FILE *outf, rtx rtx_first)
+print_rtl_with_bb (FILE *outf, const_rtx rtx_first)
 {
-  rtx tmp_rtx;
-
+  const_rtx tmp_rtx;
   if (rtx_first == 0)
     fprintf (outf, "(nil)\n");
   else
     {
       enum bb_state { NOT_IN_BB, IN_ONE_BB, IN_MULTIPLE_BB };
       int max_uid = get_max_uid ();
-      basic_block *start = xcalloc (max_uid, sizeof (basic_block));
-      basic_block *end = xcalloc (max_uid, sizeof (basic_block));
-      enum bb_state *in_bb_p = xcalloc (max_uid, sizeof (enum bb_state));
+      basic_block *start = XCNEWVEC (basic_block, max_uid);
+      basic_block *end = XCNEWVEC (basic_block, max_uid);
+      enum bb_state *in_bb_p = XCNEWVEC (enum bb_state, max_uid);
 
       basic_block bb;
 
+      if (df)
+       df_dump_start (outf);
+
       FOR_EACH_BB_REVERSE (bb)
        {
          rtx x;
@@ -1816,13 +1693,27 @@ print_rtl_with_bb (FILE *outf, rtx rtx_first)
       for (tmp_rtx = rtx_first; NULL != tmp_rtx; tmp_rtx = NEXT_INSN (tmp_rtx))
        {
          int did_output;
-
          if ((bb = start[INSN_UID (tmp_rtx)]) != NULL)
            {
-             fprintf (outf, ";; Start of basic block %d, registers live:",
-                      bb->index);
-             dump_regset (bb->il.rtl->global_live_at_start, outf);
-             putc ('\n', outf);
+             edge e;
+             edge_iterator ei;
+
+             fprintf (outf, ";; Start of basic block (");
+             FOR_EACH_EDGE (e, ei, bb->preds)
+               fprintf (outf, " %d", e->src->index);
+             fprintf (outf, ") -> %d\n", bb->index);
+
+             if (df)
+               {
+                 df_dump_top (bb, outf);
+                 putc ('\n', outf);
+               }
+             FOR_EACH_EDGE (e, ei, bb->preds)
+               {
+                 fputs (";; Pred edge ", outf);
+                 dump_edge_info (outf, e, 0);
+                 fputc ('\n', outf);
+               }
            }
 
          if (in_bb_p[INSN_UID (tmp_rtx)] == NOT_IN_BB
@@ -1836,12 +1727,27 @@ print_rtl_with_bb (FILE *outf, rtx rtx_first)
 
          if ((bb = end[INSN_UID (tmp_rtx)]) != NULL)
            {
-             fprintf (outf, ";; End of basic block %d, registers live:\n",
-                      bb->index);
-             dump_regset (bb->il.rtl->global_live_at_end, outf);
+             edge e;
+             edge_iterator ei;
+
+             fprintf (outf, ";; End of basic block %d -> (", bb->index);
+             FOR_EACH_EDGE (e, ei, bb->succs)
+               fprintf (outf, " %d", e->dest->index);
+             fprintf (outf, ")\n");
+
+             if (df)
+               {
+                 df_dump_bottom (bb, outf);
+                 putc ('\n', outf);
+               }
              putc ('\n', outf);
+             FOR_EACH_EDGE (e, ei, bb->succs)
+               {
+                 fputs (";; Succ edge ", outf);
+                 dump_edge_info (outf, e, 1);
+                 fputc ('\n', outf);
+               }
            }
-
          if (did_output)
            putc ('\n', outf);
        }
@@ -1851,10 +1757,10 @@ print_rtl_with_bb (FILE *outf, rtx rtx_first)
       free (in_bb_p);
     }
 
-  if (current_function_epilogue_delay_list != 0)
+  if (crtl->epilogue_delay_list != 0)
     {
       fprintf (outf, "\n;; Insns in epilogue delay list:\n\n");
-      for (tmp_rtx = current_function_epilogue_delay_list; tmp_rtx != 0;
+      for (tmp_rtx = crtl->epilogue_delay_list; tmp_rtx != 0;
           tmp_rtx = XEXP (tmp_rtx, 1))
        print_rtl_single (outf, XEXP (tmp_rtx, 0));
     }
@@ -1871,19 +1777,43 @@ update_br_prob_note (basic_block bb)
     return;
   XEXP (note, 0) = GEN_INT (BRANCH_EDGE (bb)->probability);
 }
+
+/* Get the last insn associated with block BB (that includes barriers and
+   tablejumps after BB).  */
+rtx
+get_last_bb_insn (basic_block bb)
+{
+  rtx tmp;
+  rtx end = BB_END (bb);
+
+  /* Include any jump table following the basic block.  */
+  if (tablejump_p (end, NULL, &tmp))
+    end = tmp;
+
+  /* Include any barriers that may follow the basic block.  */
+  tmp = next_nonnote_insn_bb (end);
+  while (tmp && BARRIER_P (tmp))
+    {
+      end = tmp;
+      tmp = next_nonnote_insn_bb (end);
+    }
+
+  return end;
+}
 \f
 /* Verify the CFG and RTL consistency common for both underlying RTL and
    cfglayout RTL.
 
    Currently it does following checks:
 
-   - test head/end pointers
    - overlapping of basic blocks
+   - insns with wrong BLOCK_FOR_INSN pointers
    - headers of basic blocks (the NOTE_INSN_BASIC_BLOCK note)
    - tails of basic blocks (ensure that boundary is necessary)
    - scans body of the basic block for JUMP_INSN, CODE_LABEL
      and NOTE_INSN_BASIC_BLOCK
    - verify that no fall_thru edge crosses hot/cold partition boundaries
+   - verify that there are no pending RTL branch predictions
 
    In future it can be extended check a lot of other stuff as well
    (reachability of basic blocks, life information, etc. etc.).  */
@@ -1891,24 +1821,14 @@ update_br_prob_note (basic_block bb)
 static int
 rtl_verify_flow_info_1 (void)
 {
-  const int max_uid = get_max_uid ();
-  rtx last_head = get_last_insn ();
-  basic_block *bb_info;
   rtx x;
   int err = 0;
   basic_block bb;
 
-  bb_info = xcalloc (max_uid, sizeof (basic_block));
-
+  /* Check the general integrity of the basic blocks.  */
   FOR_EACH_BB_REVERSE (bb)
     {
-      rtx head = BB_HEAD (bb);
-      rtx end = BB_END (bb);
-
-      /* Verify the end of the basic block is in the INSN chain.  */
-      for (x = last_head; x != NULL_RTX; x = PREV_INSN (x))
-       if (x == end)
-         break;
+      rtx insn;
 
       if (!(bb->flags & BB_RTL))
        {
@@ -1916,40 +1836,32 @@ rtl_verify_flow_info_1 (void)
          err = 1;
        }
 
-      if (!x)
-       {
-         error ("end insn %d for block %d not found in the insn stream",
-                INSN_UID (end), bb->index);
-         err = 1;
-       }
-
-      /* Work backwards from the end to the head of the basic block
-        to verify the head is in the RTL chain.  */
-      for (; x != NULL_RTX; x = PREV_INSN (x))
-       {
-         /* While walking over the insn chain, verify insns appear
-            in only one basic block and initialize the BB_INFO array
-            used by other passes.  */
-         if (bb_info[INSN_UID (x)] != NULL)
-           {
-             error ("insn %d is in multiple basic blocks (%d and %d)",
-                    INSN_UID (x), bb->index, bb_info[INSN_UID (x)]->index);
-             err = 1;
-           }
-
-         bb_info[INSN_UID (x)] = bb;
-
-         if (x == head)
-           break;
-       }
-      if (!x)
-       {
-         error ("head insn %d for block %d not found in the insn stream",
-                INSN_UID (head), bb->index);
-         err = 1;
-       }
+      FOR_BB_INSNS (bb, insn)
+       if (BLOCK_FOR_INSN (insn) != bb)
+         {
+           error ("insn %d basic block pointer is %d, should be %d",
+                  INSN_UID (insn),
+                  BLOCK_FOR_INSN (insn) ? BLOCK_FOR_INSN (insn)->index : 0,
+                  bb->index);
+           err = 1;
+         }
 
-      last_head = x;
+      for (insn = bb->il.rtl->header; insn; insn = NEXT_INSN (insn))
+       if (!BARRIER_P (insn)
+           && BLOCK_FOR_INSN (insn) != NULL)
+         {
+           error ("insn %d in header of bb %d has non-NULL basic block",
+                  INSN_UID (insn), bb->index);
+           err = 1;
+         }
+      for (insn = bb->il.rtl->footer; insn; insn = NEXT_INSN (insn))
+       if (!BARRIER_P (insn)
+           && BLOCK_FOR_INSN (insn) != NULL)
+         {
+           error ("insn %d in footer of bb %d has non-NULL basic block",
+                  INSN_UID (insn), bb->index);
+           err = 1;
+         }
     }
 
   /* Now check the basic blocks (boundaries etc.) */
@@ -1982,8 +1894,8 @@ rtl_verify_flow_info_1 (void)
                  || (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)",
+           {
+                 error ("fallthru edge crosses section boundary (bb %i)",
                         e->src->index);
                  err = 1;
                }
@@ -2005,10 +1917,14 @@ rtl_verify_flow_info_1 (void)
            n_abnormal++;
        }
 
-      if (n_eh && GET_CODE (PATTERN (BB_END (bb))) != RESX
-         && !find_reg_note (BB_END (bb), REG_EH_REGION, NULL_RTX))
+      if (n_eh && !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);
+         err = 1;
+       }
+      if (n_eh > 1)
        {
-         error ("Missing REG_EH_REGION note in the end of bb %i", bb->index);
+         error ("too many eh edges %i", bb->index);
          err = 1;
        }
       if (n_branch
@@ -2016,28 +1932,30 @@ rtl_verify_flow_info_1 (void)
              || (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 number 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 && !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
@@ -2046,7 +1964,7 @@ rtl_verify_flow_info_1 (void)
              || 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;
        }
 
@@ -2069,7 +1987,7 @@ rtl_verify_flow_info_1 (void)
          }
 
       /* OK pointers are correct.  Now check the header of basic
-         block.  It ought to contain optional CODE_LABEL followed
+        block.  It ought to contain optional CODE_LABEL followed
         by NOTE_BASIC_BLOCK.  */
       x = BB_HEAD (bb);
       if (LABEL_P (x))
@@ -2116,7 +2034,6 @@ rtl_verify_flow_info_1 (void)
     }
 
   /* Clean up.  */
-  free (bb_info);
   return err;
 }
 
@@ -2125,31 +2042,84 @@ rtl_verify_flow_info_1 (void)
 
    Currently it does following checks:
    - all checks of rtl_verify_flow_info_1
+   - test head/end pointers
    - check that all insns are in the basic blocks
      (except the switch handling code, barriers and notes)
    - check that all returns are followed by barriers
    - check that all fallthru edge points to the adjacent blocks.  */
+
 static int
 rtl_verify_flow_info (void)
 {
   basic_block bb;
   int err = rtl_verify_flow_info_1 ();
   rtx x;
+  rtx last_head = get_last_insn ();
+  basic_block *bb_info;
   int num_bb_notes;
   const rtx rtx_first = get_insns ();
   basic_block last_bb_seen = ENTRY_BLOCK_PTR, curr_bb = NULL;
+  const int max_uid = get_max_uid ();
+
+  bb_info = XCNEWVEC (basic_block, max_uid);
 
   FOR_EACH_BB_REVERSE (bb)
     {
       edge e;
       edge_iterator ei;
+      rtx head = BB_HEAD (bb);
+      rtx end = BB_END (bb);
+
+      for (x = last_head; x != NULL_RTX; x = PREV_INSN (x))
+       {
+         /* Verify the end of the basic block is in the INSN chain.  */
+         if (x == end)
+           break;
+
+         /* And that the code outside of basic blocks has NULL bb field.  */
+       if (!BARRIER_P (x)
+           && BLOCK_FOR_INSN (x) != NULL)
+         {
+           error ("insn %d outside of basic blocks has non-NULL bb field",
+                  INSN_UID (x));
+           err = 1;
+         }
+       }
+
+      if (!x)
+       {
+         error ("end insn %d for block %d not found in the insn stream",
+                INSN_UID (end), bb->index);
+         err = 1;
+       }
+
+      /* Work backwards from the end to the head of the basic block
+        to verify the head is in the RTL chain.  */
+      for (; x != NULL_RTX; x = PREV_INSN (x))
+       {
+         /* While walking over the insn chain, verify insns appear
+            in only one basic block.  */
+         if (bb_info[INSN_UID (x)] != NULL)
+           {
+             error ("insn %d is in multiple basic blocks (%d and %d)",
+                    INSN_UID (x), bb->index, bb_info[INSN_UID (x)]->index);
+             err = 1;
+           }
+
+         bb_info[INSN_UID (x)] = bb;
 
-      if (bb->predictions)
+         if (x == head)
+           break;
+       }
+      if (!x)
        {
-         error ("bb prediction set for block %i, but it is not used in RTL land", bb->index);
+         error ("head insn %d for block %d not found in the insn stream",
+                INSN_UID (head), bb->index);
          err = 1;
        }
 
+      last_head = PREV_INSN (x);
+
       FOR_EACH_EDGE (e, ei, bb->succs)
        if (e->flags & EDGE_FALLTHRU)
          break;
@@ -2158,20 +2128,21 @@ rtl_verify_flow_info (void)
          rtx insn;
 
          /* Ensure existence of barrier in BB with no fallthru edges.  */
-         for (insn = BB_END (bb); !insn || !BARRIER_P (insn);
-              insn = NEXT_INSN (insn))
-           if (!insn
-               || (NOTE_P (insn)
-                   && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK))
+         for (insn = NEXT_INSN (BB_END (bb)); ; insn = NEXT_INSN (insn))
+           {
+             if (!insn || NOTE_INSN_BASIC_BLOCK_P (insn))
                {
                  error ("missing barrier after block %i", bb->index);
                  err = 1;
                  break;
                }
+             if (BARRIER_P (insn))
+               break;
+           }
        }
       else if (e->src != ENTRY_BLOCK_PTR
               && e->dest != EXIT_BLOCK_PTR)
-        {
+       {
          rtx insn;
 
          if (e->src->next_bb != e->dest)
@@ -2191,8 +2162,22 @@ rtl_verify_flow_info (void)
                  fatal_insn ("wrong insn in the fallthru edge", insn);
                  err = 1;
                }
-        }
+       }
+    }
+
+  for (x = last_head; x != NULL_RTX; x = PREV_INSN (x))
+    {
+      /* Check that the code before the first basic block has NULL
+        bb field.  */
+      if (!BARRIER_P (x)
+         && BLOCK_FOR_INSN (x) != NULL)
+       {
+         error ("insn %d outside of basic blocks has non-NULL bb field",
+                INSN_UID (x));
+         err = 1;
+       }
     }
+  free (bb_info);
 
   num_bb_notes = 0;
   last_bb_seen = ENTRY_BLOCK_PTR;
@@ -2221,9 +2206,7 @@ rtl_verify_flow_info (void)
            case CODE_LABEL:
              /* An addr_vec is placed outside any basic block.  */
              if (NEXT_INSN (x)
-                 && JUMP_P (NEXT_INSN (x))
-                 && (GET_CODE (PATTERN (NEXT_INSN (x))) == ADDR_DIFF_VEC
-                     || GET_CODE (PATTERN (NEXT_INSN (x))) == ADDR_VEC))
+                 && JUMP_TABLE_DATA_P (NEXT_INSN (x)))
                x = NEXT_INSN (x);
 
              /* But in any case, non-deletable labels can appear anywhere.  */
@@ -2236,13 +2219,13 @@ rtl_verify_flow_info (void)
 
       if (JUMP_P (x)
          && returnjump_p (x) && ! condjump_p (x)
-         && ! (NEXT_INSN (x) && BARRIER_P (NEXT_INSN (x))))
+         && ! (next_nonnote_insn (x) && BARRIER_P (next_nonnote_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);
@@ -2263,6 +2246,11 @@ purge_dead_edges (basic_block bb)
   bool found;
   edge_iterator ei;
 
+  if (DEBUG_INSN_P (insn) && insn != BB_HEAD (bb))
+    do
+      insn = PREV_INSN (insn);
+    while ((DEBUG_INSN_P (insn) || NOTE_P (insn)) && insn != BB_HEAD (bb));
+
   /* If this instruction cannot trap, remove REG_EH_REGION notes.  */
   if (NONJUMP_INSN_P (insn)
       && (note = find_reg_note (insn, REG_EH_REGION, NULL)))
@@ -2278,33 +2266,33 @@ purge_dead_edges (basic_block bb)
   /* Cleanup abnormal edges caused by exceptions or non-local gotos.  */
   for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
     {
-      if (e->flags & EDGE_EH)
+      bool remove = false;
+
+      /* 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_ABNORMAL_CALL)
        {
-         if (can_throw_internal (BB_END (bb)))
-           {
-             ei_next (&ei);
-             continue;
-           }
+         if (!CALL_P (insn))
+           remove = true;
+         else if (can_nonlocal_goto (insn))
+           ;
+         else if ((e->flags & EDGE_EH) && can_throw_internal (insn))
+           ;
+         else
+           remove = true;
        }
-      else if (e->flags & EDGE_ABNORMAL_CALL)
+      else if (e->flags & EDGE_EH)
+       remove = !can_throw_internal (insn);
+
+      if (remove)
        {
-         if (CALL_P (BB_END (bb))
-             && (! (note = find_reg_note (insn, REG_EH_REGION, NULL))
-                 || INTVAL (XEXP (note, 0)) >= 0))
-           {
-             ei_next (&ei);
-             continue;
-           }
+         remove_edge (e);
+         df_set_bb_dirty (bb);
+         purged = true;
        }
       else
-       {
-         ei_next (&ei);
-         continue;
-       }
-
-      remove_edge (e);
-      bb->flags |= BB_DIRTY;
-      purged = true;
+       ei_next (&ei);
     }
 
   if (JUMP_P (insn))
@@ -2371,7 +2359,7 @@ purge_dead_edges (basic_block bb)
            }
 
          /* We do not need this edge.  */
-         bb->flags |= BB_DIRTY;
+         df_set_bb_dirty (bb);
          purged = true;
          remove_edge (e);
        }
@@ -2443,7 +2431,7 @@ purge_dead_edges (basic_block bb)
     {
       if (!(e->flags & (EDGE_FALLTHRU | EDGE_FAKE)))
        {
-         bb->flags |= BB_DIRTY;
+         df_set_bb_dirty (bb);
          remove_edge (e);
          purged = true;
        }
@@ -2486,7 +2474,7 @@ purge_all_dead_edges (void)
 static basic_block
 cfg_layout_split_block (basic_block bb, void *insnp)
 {
-  rtx insn = insnp;
+  rtx insn = (rtx) insnp;
   basic_block new_bb = rtl_split_block (bb, insn);
 
   new_bb->il.rtl->footer = bb->il.rtl->footer;
@@ -2495,7 +2483,6 @@ cfg_layout_split_block (basic_block bb, void *insnp)
   return new_bb;
 }
 
-
 /* Redirect Edge to DEST.  */
 static edge
 cfg_layout_redirect_edge_and_branch (edge e, basic_block dest)
@@ -2512,7 +2499,7 @@ cfg_layout_redirect_edge_and_branch (edge e, basic_block dest)
   if (e->src != ENTRY_BLOCK_PTR
       && (ret = try_redirect_by_replacing_jump (e, dest, true)))
     {
-      src->flags |= BB_DIRTY;
+      df_set_bb_dirty (src);
       return ret;
     }
 
@@ -2523,7 +2510,7 @@ cfg_layout_redirect_edge_and_branch (edge e, basic_block dest)
        fprintf (dump_file, "Redirecting entry edge from bb %i to %i\n",
                 e->src->index, dest->index);
 
-      e->src->flags |= BB_DIRTY;
+      df_set_bb_dirty (e->src);
       redirect_edge_succ (e, dest);
       return e;
     }
@@ -2540,7 +2527,7 @@ cfg_layout_redirect_edge_and_branch (edge e, basic_block dest)
                                     BB_END (src)))
        {
          edge redirected;
-         
+
          if (dump_file)
            fprintf (dump_file, "Fallthru edge unified with branch "
                     "%i->%i redirected to %i\n",
@@ -2549,11 +2536,11 @@ cfg_layout_redirect_edge_and_branch (edge e, basic_block dest)
          redirected = redirect_branch_edge (e, dest);
          gcc_assert (redirected);
          e->flags |= EDGE_FALLTHRU;
-          e->src->flags |= BB_DIRTY;
+         df_set_bb_dirty (e->src);
          return e;
        }
       /* In case we are redirecting fallthru edge to the branch edge
-         of conditional jump, remove it.  */
+        of conditional jump, remove it.  */
       if (EDGE_COUNT (src->succs) == 2)
        {
          /* Find the edge that is different from E.  */
@@ -2575,7 +2562,7 @@ cfg_layout_redirect_edge_and_branch (edge e, basic_block dest)
   /* We don't want simplejumps in the insn stream during cfglayout.  */
   gcc_assert (!simplejump_p (BB_END (src)));
 
-  src->flags |= BB_DIRTY;
+  df_set_bb_dirty (src);
   return ret;
 }
 
@@ -2673,6 +2660,7 @@ cfg_layout_delete_block (basic_block bb)
 }
 
 /* Return true when blocks A and B can be safely merged.  */
+
 static bool
 cfg_layout_can_merge_blocks_p (basic_block a, basic_block b)
 {
@@ -2681,9 +2669,9 @@ cfg_layout_can_merge_blocks_p (basic_block a, basic_block b)
      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 
+     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))
@@ -2697,10 +2685,11 @@ cfg_layout_can_merge_blocks_p (basic_block a, basic_block b)
          /* Must be simple edge.  */
          && !(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.  */
+         /* If the jump insn has side effects, we can't kill the edge.
+            When not optimizing, try_redirect_by_replacing_jump will
+            not allow us to redirect an edge by replacing a table jump.  */
          && (!JUMP_P (BB_END (a))
-             || (reload_completed
+             || ((!optimize || reload_completed)
                  ? simplejump_p (BB_END (a)) : onlyjump_p (BB_END (a)))));
 }
 
@@ -2713,9 +2702,14 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
   gcc_assert (cfg_layout_can_merge_blocks_p (a, b));
 #endif
 
+  if (dump_file)
+    fprintf (dump_file, "merging block %d into block %d\n", b->index, a->index);
+
   /* If there was a CODE_LABEL beginning B, delete it.  */
   if (LABEL_P (BB_HEAD (b)))
-    delete_insn (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.  */
@@ -2723,13 +2717,41 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
     try_redirect_by_replacing_jump (EDGE_SUCC (a, 0), b, true);
   gcc_assert (!JUMP_P (BB_END (a)));
 
+  /* When not optimizing and the edge is the only place in RTL which holds
+     some unique locus, emit a nop with that locus in between.  */
+  if (!optimize && EDGE_SUCC (a, 0)->goto_locus)
+    {
+      rtx insn = BB_END (a), end = PREV_INSN (BB_HEAD (a));
+      int goto_locus = EDGE_SUCC (a, 0)->goto_locus;
+
+      while (insn != end && (!INSN_P (insn) || INSN_LOCATOR (insn) == 0))
+       insn = PREV_INSN (insn);
+      if (insn != end && locator_eq (INSN_LOCATOR (insn), goto_locus))
+       goto_locus = 0;
+      else
+       {
+         insn = BB_HEAD (b);
+         end = NEXT_INSN (BB_END (b));
+         while (insn != end && !INSN_P (insn))
+           insn = NEXT_INSN (insn);
+         if (insn != end && INSN_LOCATOR (insn) != 0
+             && locator_eq (INSN_LOCATOR (insn), goto_locus))
+           goto_locus = 0;
+       }
+      if (goto_locus)
+       {
+         BB_END (a) = emit_insn_after_noloc (gen_nop (), BB_END (a), a);
+         INSN_LOCATOR (BB_END (a)) = goto_locus;
+       }
+    }
+
   /* Possible line number notes should appear in between.  */
   if (b->il.rtl->header)
     {
       rtx first = BB_END (a), last;
 
-      last = emit_insn_after_noloc (b->il.rtl->header, BB_END (a));
-      delete_insn_chain (NEXT_INSN (first), last);
+      last = emit_insn_after_noloc (b->il.rtl->header, BB_END (a), a);
+      delete_insn_chain (NEXT_INSN (first), last, false);
       b->il.rtl->header = NULL;
     }
 
@@ -2738,12 +2760,19 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
     {
       rtx first = unlink_insn_chain (BB_HEAD (b), BB_END (b));
 
-      emit_insn_after_noloc (first, BB_END (a));
+      emit_insn_after_noloc (first, BB_END (a), a);
       /* Skip possible DELETED_LABEL insn.  */
       if (!NOTE_INSN_BASIC_BLOCK_P (first))
        first = NEXT_INSN (first);
       gcc_assert (NOTE_INSN_BASIC_BLOCK_P (first));
       BB_HEAD (b) = NULL;
+
+      /* emit_insn_after_noloc doesn't call df_insn_change_bb.
+         We need to explicitly call. */
+      update_bb_for_insn_chain (NEXT_INSN (first),
+                               BB_END (b),
+                               a);
+
       delete_insn (first);
     }
   /* Otherwise just re-associate the instructions.  */
@@ -2751,10 +2780,8 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
     {
       rtx insn;
 
-      for (insn = BB_HEAD (b);
-          insn != NEXT_INSN (BB_END (b));
-          insn = NEXT_INSN (insn))
-       set_block_for_insn (insn, a);
+      update_bb_for_insn_chain (BB_HEAD (b), BB_END (b), a);
+
       insn = BB_HEAD (b);
       /* Skip possible DELETED_LABEL insn.  */
       if (!NOTE_INSN_BASIC_BLOCK_P (insn))
@@ -2765,6 +2792,8 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
       delete_insn (insn);
     }
 
+  df_bb_delete (b->index);
+
   /* Possible tablejumps and barriers should appear after the block.  */
   if (b->il.rtl->footer)
     {
@@ -2781,7 +2810,6 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
        }
       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",
@@ -2798,18 +2826,10 @@ cfg_layout_split_edge (edge e)
                        ? NEXT_INSN (BB_END (e->src)) : get_insns (),
                        NULL_RTX, e->src);
 
-  /* ??? 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);
-    }
-
+  if (e->dest == EXIT_BLOCK_PTR)
+    BB_COPY_PARTITION (new_bb, e->src);
+  else
+    BB_COPY_PARTITION (new_bb, e->dest);
   make_edge (new_bb, e->dest, EDGE_FALLTHRU);
   redirect_edge_and_branch_force (e, new_bb);
 
@@ -2833,7 +2853,9 @@ rtl_block_ends_with_call_p (basic_block bb)
 
   while (!CALL_P (insn)
         && insn != BB_HEAD (bb)
-        && keep_with_call_p (insn))
+        && (keep_with_call_p (insn)
+            || NOTE_P (insn)
+            || DEBUG_INSN_P (insn)))
     insn = PREV_INSN (insn);
   return (CALL_P (insn));
 }
@@ -2841,7 +2863,7 @@ rtl_block_ends_with_call_p (basic_block bb)
 /* Return 1 if BB ends with a conditional branch, 0 otherwise.  */
 
 static bool
-rtl_block_ends_with_condjump_p (basic_block bb)
+rtl_block_ends_with_condjump_p (const_basic_block bb)
 {
   return any_condjump_p (BB_END (bb));
 }
@@ -2850,7 +2872,7 @@ rtl_block_ends_with_condjump_p (basic_block bb)
    Helper function for rtl_flow_call_edges_add.  */
 
 static bool
-need_fake_edge_p (rtx insn)
+need_fake_edge_p (const_rtx insn)
 {
   if (!INSN_P (insn))
     return false;
@@ -2858,7 +2880,7 @@ need_fake_edge_p (rtx insn)
   if ((CALL_P (insn)
        && !SIBLING_CALL_P (insn)
        && !find_reg_note (insn, REG_NORETURN, NULL)
-       && !CONST_OR_PURE_CALL_P (insn)))
+       && !(RTL_CONST_OR_PURE_CALL_P (insn))))
     return true;
 
   return ((GET_CODE (PATTERN (insn)) == ASM_OPERANDS
@@ -2885,7 +2907,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)
@@ -2922,7 +2944,7 @@ rtl_flow_call_edges_add (sbitmap blocks)
          e = find_edge (bb, EXIT_BLOCK_PTR);
          if (e)
            {
-             insert_insn_on_edge (gen_rtx_USE (VOIDmode, const0_rtx), e);
+             insert_insn_on_edge (gen_use (const0_rtx), e);
              commit_edge_insertions ();
            }
        }
@@ -2932,7 +2954,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;
@@ -2953,14 +2975,14 @@ rtl_flow_call_edges_add (sbitmap blocks)
              rtx split_at_insn = insn;
 
              /* Don't split the block between a call and an insn that should
-                remain in the same block as the call.  */
+                remain in the same block as the call.  */
              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);
 
              /* The handling above of the final block before the epilogue
-                should be enough to verify that there is no edge to the exit
+                should be enough to verify that there is no edge to the exit
                 block in CFG already.  Calling make_edge in such case would
                 cause us to mark that edge as fake and remove it later.  */
 
@@ -3002,8 +3024,8 @@ rtl_flow_call_edges_add (sbitmap blocks)
    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)  
+                           basic_block second_head ATTRIBUTE_UNUSED,
+                           basic_block cond_bb, void *comp_rtx)
 {
   rtx label, seq, jump;
   rtx op0 = XEXP ((rtx)comp_rtx, 0);
@@ -3021,7 +3043,7 @@ rtl_lv_add_condition_to_bb (basic_block first_head ,
   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);
+                          mode, NULL_RTX, NULL_RTX, label, -1);
   jump = get_last_insn ();
   JUMP_LABEL (jump) = label;
   LABEL_NUSES (label)++;
@@ -3058,9 +3080,128 @@ void
 init_rtl_bb_info (basic_block bb)
 {
   gcc_assert (!bb->il.rtl);
-  bb->il.rtl = ggc_alloc_cleared (sizeof (struct rtl_bb_info));
+  bb->il.rtl = GGC_CNEW (struct rtl_bb_info);
+}
+
+
+/* Add EXPR to the end of basic block BB.  */
+
+rtx
+insert_insn_end_bb_new (rtx pat, basic_block bb)
+{
+  rtx insn = BB_END (bb);
+  rtx new_insn;
+  rtx pat_end = pat;
+
+  while (NEXT_INSN (pat_end) != NULL_RTX)
+    pat_end = NEXT_INSN (pat_end);
+
+  /* If the last insn is a jump, insert EXPR in front [taking care to
+     handle cc0, etc. properly].  Similarly we need to care trapping
+     instructions in presence of non-call exceptions.  */
+
+  if (JUMP_P (insn)
+      || (NONJUMP_INSN_P (insn)
+          && (!single_succ_p (bb)
+              || single_succ_edge (bb)->flags & EDGE_ABNORMAL)))
+    {
+#ifdef HAVE_cc0
+      rtx note;
+#endif
+      /* If this is a jump table, then we can't insert stuff here.  Since
+         we know the previous real insn must be the tablejump, we insert
+         the new instruction just before the tablejump.  */
+      if (GET_CODE (PATTERN (insn)) == ADDR_VEC
+          || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
+        insn = prev_real_insn (insn);
+
+#ifdef HAVE_cc0
+      /* FIXME: 'twould be nice to call prev_cc0_setter here but it aborts
+         if cc0 isn't set.  */
+      note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
+      if (note)
+        insn = XEXP (note, 0);
+      else
+        {
+          rtx maybe_cc0_setter = prev_nonnote_insn (insn);
+          if (maybe_cc0_setter
+              && INSN_P (maybe_cc0_setter)
+              && sets_cc0_p (PATTERN (maybe_cc0_setter)))
+            insn = maybe_cc0_setter;
+        }
+#endif
+      /* FIXME: What if something in cc0/jump uses value set in new
+         insn?  */
+      new_insn = emit_insn_before_noloc (pat, insn, bb);
+    }
+
+  /* Likewise if the last insn is a call, as will happen in the presence
+     of exception handling.  */
+  else if (CALL_P (insn)
+           && (!single_succ_p (bb)
+               || single_succ_edge (bb)->flags & EDGE_ABNORMAL))
+    {
+      /* Keeping in mind targets with small register classes and parameters
+         in registers, we search backward and place the instructions before
+        the first parameter is loaded.  Do this for everyone for consistency
+        and a presumption that we'll get better code elsewhere as well.  */
+
+      /* Since different machines initialize their parameter registers
+         in different orders, assume nothing.  Collect the set of all
+         parameter registers.  */
+      insn = find_first_parameter_load (insn, BB_HEAD (bb));
+
+      /* If we found all the parameter loads, then we want to insert
+         before the first parameter load.
+
+         If we did not find all the parameter loads, then we might have
+         stopped on the head of the block, which could be a CODE_LABEL.
+         If we inserted before the CODE_LABEL, then we would be putting
+         the insn in the wrong basic block.  In that case, put the insn
+         after the CODE_LABEL.  Also, respect NOTE_INSN_BASIC_BLOCK.  */
+      while (LABEL_P (insn)
+             || NOTE_INSN_BASIC_BLOCK_P (insn))
+        insn = NEXT_INSN (insn);
+
+      new_insn = emit_insn_before_noloc (pat, insn, bb);
+    }
+  else
+    new_insn = emit_insn_after_noloc (pat, insn, bb);
+
+  return new_insn;
 }
 
+/* Returns true if it is possible to remove edge E by redirecting
+   it to the destination of the other edge from E->src.  */
+
+static bool
+rtl_can_remove_branch_p (const_edge e)
+{
+  const_basic_block src = e->src;
+  const_basic_block target = EDGE_SUCC (src, EDGE_SUCC (src, 0) == e)->dest;
+  const_rtx insn = BB_END (src), set;
+
+  /* The conditions are taken from try_redirect_by_replacing_jump.  */
+  if (target == EXIT_BLOCK_PTR)
+    return false;
+
+  if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
+    return false;
+
+  if (find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)
+      || BB_PARTITION (src) != BB_PARTITION (target))
+    return false;
+
+  if (!onlyjump_p (insn)
+      || tablejump_p (insn, NULL, NULL))
+    return false;
+
+  set = single_set (insn);
+  if (!set || side_effects_p (set))
+    return false;
+
+  return true;
+}
 
 /* Implementation of CFG manipulation for linearized RTL.  */
 struct cfg_hooks rtl_cfg_hooks = {
@@ -3070,6 +3211,7 @@ struct cfg_hooks rtl_cfg_hooks = {
   rtl_create_basic_block,
   rtl_redirect_edge_and_branch,
   rtl_redirect_edge_and_branch_force,
+  rtl_can_remove_branch_p,
   rtl_delete_block,
   rtl_split_block,
   rtl_move_block_after,
@@ -3091,7 +3233,7 @@ struct cfg_hooks rtl_cfg_hooks = {
   NULL, /* lv_add_condition_to_bb */
   NULL, /* lv_adjust_loop_header_phi*/
   NULL, /* extract_cond_bb_edges */
-  NULL                 /* flush_pending_stmts */
+  NULL         /* flush_pending_stmts */
 };
 
 /* Implementation of CFG manipulation for cfg layout RTL, where
@@ -3102,8 +3244,8 @@ struct cfg_hooks rtl_cfg_hooks = {
 /* We do not want to declare these functions in a header file, since they
    should only be used through the cfghooks interface, and we do not want to
    move them here since it would require also moving quite a lot of related
-   code.  */
-extern bool cfg_layout_can_duplicate_bb_p (basic_block);
+   code.  They are in cfglayout.c.  */
+extern bool cfg_layout_can_duplicate_bb_p (const_basic_block);
 extern basic_block cfg_layout_duplicate_bb (basic_block);
 
 struct cfg_hooks cfg_layout_rtl_cfg_hooks = {
@@ -3113,6 +3255,7 @@ struct cfg_hooks cfg_layout_rtl_cfg_hooks = {
   cfg_layout_create_basic_block,
   cfg_layout_redirect_edge_and_branch,
   cfg_layout_redirect_edge_and_branch_force,
+  rtl_can_remove_branch_p,
   cfg_layout_delete_block,
   cfg_layout_split_block,
   rtl_move_block_after,
@@ -3134,6 +3277,5 @@ struct cfg_hooks cfg_layout_rtl_cfg_hooks = {
   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 */  
+  NULL         /* flush_pending_stmts */
 };
-