OSDN Git Service

* jump.c (mark_all_labels): Work in cfglayout mode.
[pf3gnuchains/gcc-fork.git] / gcc / cfgcleanup.c
index 8ac3405..ad9ae4f 100644 (file)
@@ -1,6 +1,6 @@
 /* Control flow optimization 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 optimizer of the control flow.  The main entry point is
    cleanup_cfg.  Following optimizations are performed:
@@ -37,7 +37,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tm.h"
 #include "rtl.h"
 #include "hard-reg-set.h"
-#include "basic-block.h"
+#include "regs.h"
 #include "timevar.h"
 #include "output.h"
 #include "insn-config.h"
@@ -48,27 +48,13 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "params.h"
 #include "tm_p.h"
 #include "target.h"
-#include "regs.h"
 #include "cfglayout.h"
 #include "emit-rtl.h"
+#include "tree-pass.h"
+#include "cfgloop.h"
+#include "expr.h"
 
-/* cleanup_cfg maintains following flags for each basic block.  */
-
-enum bb_flags
-{
-    /* Set if BB is the forwarder block to avoid too many
-       forwarder_block_p calls.  */
-    BB_FORWARDER_BLOCK = 1,
-    BB_NONTHREADABLE_BLOCK = 2
-};
-
-#define BB_FLAGS(BB) (enum bb_flags) (BB)->aux
-#define BB_SET_FLAG(BB, FLAG) \
-  (BB)->aux = (void *) (long) ((enum bb_flags) (BB)->aux | (FLAG))
-#define BB_CLEAR_FLAG(BB, FLAG) \
-  (BB)->aux = (void *) (long) ((enum bb_flags) (BB)->aux & ~(FLAG))
-
-#define FORWARDER_BLOCK_P(BB) (BB_FLAGS (BB) & BB_FORWARDER_BLOCK)
+#define FORWARDER_BLOCK_P(BB) ((BB)->flags & BB_FORWARDER_BLOCK)
 
 /* Set to true when we are running first pass of try_optimize_cfg loop.  */
 static bool first_pass;
@@ -76,7 +62,7 @@ static bool try_crossjump_to_edge (int, edge, edge);
 static bool try_crossjump_bb (int, basic_block);
 static bool outgoing_edges_match (int, basic_block, basic_block);
 static int flow_find_cross_jump (int, basic_block, basic_block, rtx *, rtx *);
-static bool insns_match_p (int, rtx, rtx);
+static bool old_insns_match_p (int, rtx, rtx);
 
 static void merge_blocks_move_predecessor_nojumps (basic_block, basic_block);
 static void merge_blocks_move_successor_nojumps (basic_block, basic_block);
@@ -99,7 +85,7 @@ notice_new_block (basic_block bb)
     return;
 
   if (forwarder_block_p (bb))
-    BB_SET_FLAG (bb, BB_FORWARDER_BLOCK);
+    bb->flags |= BB_FORWARDER_BLOCK;
 }
 
 /* Recompute forwarder flag after block has been modified.  */
@@ -108,9 +94,9 @@ static void
 update_forwarder_flag (basic_block bb)
 {
   if (forwarder_block_p (bb))
-    BB_SET_FLAG (bb, BB_FORWARDER_BLOCK);
+    bb->flags |= BB_FORWARDER_BLOCK;
   else
-    BB_CLEAR_FLAG (bb, BB_FORWARDER_BLOCK);
+    bb->flags &= ~BB_FORWARDER_BLOCK;
 }
 \f
 /* Simplify a conditional jump around an unconditional jump.
@@ -140,25 +126,24 @@ try_simplify_condjump (basic_block cbranch_block)
      be the last block in the function, and must contain just the
      unconditional jump.  */
   jump_block = cbranch_fallthru_edge->dest;
-  if (EDGE_COUNT (jump_block->preds) >= 2
+  if (!single_pred_p (jump_block)
       || jump_block->next_bb == EXIT_BLOCK_PTR
       || !FORWARDER_BLOCK_P (jump_block))
     return false;
-  jump_dest_block = EDGE_SUCC (jump_block, 0)->dest;
+  jump_dest_block = single_succ (jump_block);
 
   /* 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 
+     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
-      && (BB_PARTITION (jump_block) != BB_PARTITION (jump_dest_block)
-         || (cbranch_jump_edge->flags & EDGE_CROSSING)))
+  if (BB_PARTITION (jump_block) != BB_PARTITION (jump_dest_block)
+      || (cbranch_jump_edge->flags & EDGE_CROSSING))
     return false;
 
   /* The conditional branch must target the block after the
@@ -207,7 +192,7 @@ mark_effect (rtx exp, regset nonequal)
   switch (GET_CODE (exp))
     {
       /* In case we do clobber the register, mark it as equal, as we know the
-         value is dead so it don't have to match.  */
+        value is dead so it don't have to match.  */
     case CLOBBER:
       if (REG_P (XEXP (exp, 0)))
        {
@@ -279,12 +264,12 @@ thread_jump (int mode, edge e, basic_block b)
   rtx set1, set2, cond1, cond2, insn;
   enum rtx_code code1, code2, reversed_code2;
   bool reverse1 = false;
-  int i;
+  unsigned i;
   regset nonequal;
   bool failed = false;
   reg_set_iterator rsi;
 
-  if (BB_FLAGS (b) & BB_NONTHREADABLE_BLOCK)
+  if (b->flags & BB_NONTHREADABLE_BLOCK)
     return NULL;
 
   /* At the moment, we do handle only conditional jumps, but later we may
@@ -293,7 +278,7 @@ thread_jump (int mode, edge e, basic_block b)
     return NULL;
   if (EDGE_COUNT (b->succs) != 2)
     {
-      BB_SET_FLAG (b, BB_NONTHREADABLE_BLOCK);
+      b->flags |= BB_NONTHREADABLE_BLOCK;
       return NULL;
     }
 
@@ -303,7 +288,7 @@ thread_jump (int mode, edge e, basic_block b)
 
   if (!any_condjump_p (BB_END (b)) || !onlyjump_p (BB_END (b)))
     {
-      BB_SET_FLAG (b, BB_NONTHREADABLE_BLOCK);
+      b->flags |= BB_NONTHREADABLE_BLOCK;
       return NULL;
     }
 
@@ -341,26 +326,28 @@ thread_jump (int mode, edge e, basic_block b)
        insn = NEXT_INSN (insn))
     if (INSN_P (insn) && side_effects_p (PATTERN (insn)))
       {
-       BB_SET_FLAG (b, BB_NONTHREADABLE_BLOCK);
+       b->flags |= BB_NONTHREADABLE_BLOCK;
        return NULL;
       }
 
   cselib_init (false);
 
   /* First process all values computed in the source basic block.  */
-  for (insn = NEXT_INSN (BB_HEAD (e->src)); insn != NEXT_INSN (BB_END (e->src));
+  for (insn = NEXT_INSN (BB_HEAD (e->src));
+       insn != NEXT_INSN (BB_END (e->src));
        insn = NEXT_INSN (insn))
     if (INSN_P (insn))
       cselib_process_insn (insn);
 
-  nonequal = BITMAP_XMALLOC();
+  nonequal = BITMAP_ALLOC (NULL);
   CLEAR_REG_SET (nonequal);
 
   /* Now assume that we've continued by the edge E to B and continue
      processing as if it were same basic block.
      Our goal is to prove that whole block is an NOOP.  */
 
-  for (insn = NEXT_INSN (BB_HEAD (b)); insn != NEXT_INSN (BB_END (b)) && !failed;
+  for (insn = NEXT_INSN (BB_HEAD (b));
+       insn != NEXT_INSN (BB_END (b)) && !failed;
        insn = NEXT_INSN (insn))
     {
       if (INSN_P (insn))
@@ -369,7 +356,7 @@ thread_jump (int mode, edge e, basic_block b)
 
          if (GET_CODE (pat) == PARALLEL)
            {
-             for (i = 0; i < XVECLEN (pat, 0); i++)
+             for (i = 0; i < (unsigned)XVECLEN (pat, 0); i++)
                failed |= mark_effect (XVECEXP (pat, 0, i), nonequal);
            }
          else
@@ -383,7 +370,7 @@ thread_jump (int mode, edge e, basic_block b)
      have life information in cfg_cleanup.  */
   if (failed)
     {
-      BB_SET_FLAG (b, BB_NONTHREADABLE_BLOCK);
+      b->flags |= BB_NONTHREADABLE_BLOCK;
       goto failed_exit;
     }
 
@@ -395,12 +382,12 @@ thread_jump (int mode, edge e, basic_block b)
   /* In case liveness information is available, we need to prove equivalence
      only of the live values.  */
   if (mode & CLEANUP_UPDATE_LIFE)
-    AND_REG_SET (nonequal, b->global_live_at_end);
+    AND_REG_SET (nonequal, b->il.rtl->global_live_at_end);
 
   EXECUTE_IF_SET_IN_REG_SET (nonequal, 0, i, rsi)
     goto failed_exit;
 
-  BITMAP_XFREE (nonequal);
+  BITMAP_FREE (nonequal);
   cselib_finish ();
   if ((comparison_dominates_p (code1, code2) != 0)
       != (XEXP (SET_SRC (set2), 1) == pc_rtx))
@@ -409,7 +396,7 @@ thread_jump (int mode, edge e, basic_block b)
     return FALLTHRU_EDGE (b);
 
 failed_exit:
-  BITMAP_XFREE (nonequal);
+  BITMAP_FREE (nonequal);
   cselib_finish ();
   return NULL;
 }
@@ -426,16 +413,15 @@ try_forward_edges (int mode, 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. 
-  
+     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 m
-     ust be left untouched (they are required to make it safely across 
-     partition boundaries).  See the comments at the top of 
+     ust 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 (BB_END (b), REG_CROSSING_JUMP, NULL_RTX))
+  if (find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX))
     return false;
 
   for (ei = ei_start (b->succs); (e = ei_safe_edge (ei)); )
@@ -448,9 +434,9 @@ try_forward_edges (int mode, basic_block b)
 
       /* Skip complex edges because we don't know how to update them.
 
-         Still handle fallthru edges, as we can succeed to forward fallthru
-         edge to the same place as the branch edge of conditional branch
-         and turn conditional branch to an unconditional branch.  */
+        Still handle fallthru edges, as we can succeed to forward fallthru
+        edge to the same place as the branch edge of conditional branch
+        and turn conditional branch to an unconditional branch.  */
       if (e->flags & EDGE_COMPLEX)
        {
          ei_next (&ei);
@@ -458,20 +444,19 @@ try_forward_edges (int mode, basic_block b)
        }
 
       target = first = e->dest;
-      counter = 0;
+      counter = NUM_FIXED_BLOCKS;
 
       /* If we are partitioning hot/cold basic_blocks, we don't want to mess
         up jumps that cross between hot/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 
+        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
-         && first != EXIT_BLOCK_PTR
+      if (first != EXIT_BLOCK_PTR
          && find_reg_note (BB_END (first), REG_CROSSING_JUMP, NULL_RTX))
        return false;
 
@@ -482,13 +467,13 @@ try_forward_edges (int mode, basic_block b)
          may_thread |= target->flags & BB_DIRTY;
 
          if (FORWARDER_BLOCK_P (target)
-             && !(EDGE_SUCC (target, 0)->flags & EDGE_CROSSING)
-             && EDGE_SUCC (target, 0)->dest != EXIT_BLOCK_PTR)
+             && !(single_succ_edge (target)->flags & EDGE_CROSSING)
+             && single_succ (target) != EXIT_BLOCK_PTR)
            {
              /* Bypass trivial infinite loops.  */
-             if (target == EDGE_SUCC (target, 0)->dest)
+             new_target = single_succ (target);
+             if (target == new_target)
                counter = n_basic_blocks;
-             new_target = EDGE_SUCC (target, 0)->dest;
            }
 
          /* Allow to thread only over one edge at time to simplify updating
@@ -499,8 +484,7 @@ try_forward_edges (int mode, basic_block b)
              if (t)
                {
                  if (!threaded_edges)
-                   threaded_edges = xmalloc (sizeof (*threaded_edges)
-                                             * n_basic_blocks);
+                   threaded_edges = XNEWVEC (edge, n_basic_blocks);
                  else
                    {
                      int i;
@@ -521,7 +505,7 @@ try_forward_edges (int mode, basic_block b)
                  if (t->dest == b)
                    break;
 
-                 gcc_assert (nthreaded_edges < n_basic_blocks);
+                 gcc_assert (nthreaded_edges < n_basic_blocks - NUM_FIXED_BLOCKS);
                  threaded_edges[nthreaded_edges++] = t;
 
                  new_target = t->dest;
@@ -532,39 +516,6 @@ try_forward_edges (int mode, basic_block b)
          if (!new_target)
            break;
 
-         /* Avoid killing of loop pre-headers, as it is the place loop
-            optimizer wants to hoist code to.
-
-            For fallthru forwarders, the LOOP_BEG note must appear between
-            the header of block and CODE_LABEL of the loop, for non forwarders
-            it must appear before the JUMP_INSN.  */
-         if ((mode & CLEANUP_PRE_LOOP) && optimize)
-           {
-             rtx insn = (EDGE_SUCC (target, 0)->flags & EDGE_FALLTHRU
-                         ? BB_HEAD (target) : prev_nonnote_insn (BB_END (target)));
-
-             if (!NOTE_P (insn))
-               insn = NEXT_INSN (insn);
-
-             for (; insn && !LABEL_P (insn) && !INSN_P (insn);
-                  insn = NEXT_INSN (insn))
-               if (NOTE_P (insn)
-                   && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
-                 break;
-
-             if (NOTE_P (insn))
-               break;
-
-             /* Do not clean up branches to just past the end of a loop
-                at this time; it can mess up the loop optimizer's
-                recognition of some patterns.  */
-
-             insn = PREV_INSN (BB_HEAD (target));
-             if (insn && NOTE_P (insn)
-                   && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
-               break;
-           }
-
          counter++;
          target = new_target;
          threaded |= new_target_threaded;
@@ -611,13 +562,13 @@ try_forward_edges (int mode, basic_block b)
                            / REG_BR_PROB_BASE);
 
          if (!FORWARDER_BLOCK_P (b) && forwarder_block_p (b))
-           BB_SET_FLAG (b, BB_FORWARDER_BLOCK);
+           b->flags |= BB_FORWARDER_BLOCK;
 
          do
            {
              edge t;
 
-             if (EDGE_COUNT (first->succs) > 1)
+             if (!single_succ_p (first))
                {
                  gcc_assert (n < nthreaded_edges);
                  t = threaded_edges [n++];
@@ -641,7 +592,7 @@ try_forward_edges (int mode, basic_block b)
                  if (n < nthreaded_edges
                      && first == threaded_edges [n]->src)
                    n++;
-                 t = EDGE_SUCC (first, 0);
+                 t = single_succ_edge (first);
                }
 
              t->count -= edge_count;
@@ -676,16 +627,14 @@ merge_blocks_move_predecessor_nojumps (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 (flag_reorder_blocks_and_partition
-      && (BB_PARTITION (a) != BB_PARTITION (b)
-         || find_reg_note (BB_END (a), REG_CROSSING_JUMP, NULL_RTX)))
+  if (BB_PARTITION (a) != BB_PARTITION (b))
     return;
 
   barrier = next_nonnote_insn (BB_END (a));
@@ -733,17 +682,15 @@ merge_blocks_move_successor_nojumps (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. 
-  
+     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 (flag_reorder_blocks_and_partition
-      && (find_reg_note (BB_END (a), REG_CROSSING_JUMP, NULL_RTX)
-         || BB_PARTITION (a) != BB_PARTITION (b)))
+  if (BB_PARTITION (a) != BB_PARTITION (b))
     return;
 
   real_b_end = BB_END (b);
@@ -770,7 +717,7 @@ merge_blocks_move_successor_nojumps (basic_block a, basic_block b)
      necessary.  */
   only_notes = squeeze_notes (&BB_HEAD (b), &BB_END (b));
   gcc_assert (!only_notes);
-  
+
 
   /* Scramble the insn chain.  */
   reorder_insns_nobb (BB_HEAD (b), BB_END (b), BB_END (a));
@@ -805,21 +752,16 @@ merge_blocks_move (edge e, basic_block b, basic_block c, int mode)
 
   /* 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 
+     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 (BB_END (b), REG_CROSSING_JUMP, NULL_RTX)
-         || find_reg_note (BB_END (c), REG_CROSSING_JUMP, NULL_RTX)
-         || BB_PARTITION (b) != BB_PARTITION (c)))
+  if (BB_PARTITION (b) != BB_PARTITION (c))
     return NULL;
-      
-    
 
   /* If B has a fallthru edge to C, no need to move anything.  */
   if (e->flags & EDGE_FALLTHRU)
@@ -845,7 +787,7 @@ merge_blocks_move (edge e, basic_block b, basic_block c, int mode)
       edge_iterator ei;
 
       /* Avoid overactive code motion, as the forwarder blocks should be
-         eliminated by edge redirection instead.  One exception might have
+        eliminated by edge redirection instead.  One exception might have
         been if B is a forwarder block and C has no fallthru edge, but
         that should be cleaned up by bb-reorder instead.  */
       if (FORWARDER_BLOCK_P (b) || FORWARDER_BLOCK_P (c))
@@ -877,7 +819,7 @@ merge_blocks_move (edge e, basic_block b, basic_block c, int mode)
       if (! c_has_outgoing_fallthru)
        {
          merge_blocks_move_successor_nojumps (b, c);
-          return next == ENTRY_BLOCK_PTR ? next->next_bb : next;
+         return next == ENTRY_BLOCK_PTR ? next->next_bb : next;
        }
 
       /* If B does not have an incoming fallthru, then it can be moved
@@ -934,7 +876,7 @@ merge_memattrs (rtx x, rtx y)
        MEM_ATTRS (y) = 0;
       else if (! MEM_ATTRS (y))
        MEM_ATTRS (x) = 0;
-      else 
+      else
        {
          rtx mem_size;
 
@@ -943,7 +885,7 @@ merge_memattrs (rtx x, rtx y)
              set_mem_alias_set (x, 0);
              set_mem_alias_set (y, 0);
            }
-         
+
          if (! mem_expr_equal_p (MEM_EXPR (x), MEM_EXPR (y)))
            {
              set_mem_expr (x, 0);
@@ -956,7 +898,7 @@ merge_memattrs (rtx x, rtx y)
              set_mem_offset (x, 0);
              set_mem_offset (y, 0);
            }
-        
+
          if (!MEM_SIZE (x))
            mem_size = NULL_RTX;
          else if (!MEM_SIZE (y))
@@ -971,7 +913,7 @@ merge_memattrs (rtx x, rtx y)
          set_mem_align (y, MEM_ALIGN (x));
        }
     }
-  
+
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
@@ -998,7 +940,7 @@ merge_memattrs (rtx x, rtx y)
 /* Return true if I1 and I2 are equivalent and thus can be crossjumped.  */
 
 static bool
-insns_match_p (int mode ATTRIBUTE_UNUSED, rtx i1, rtx i2)
+old_insns_match_p (int mode ATTRIBUTE_UNUSED, rtx i1, rtx i2)
 {
   rtx p1, p2;
 
@@ -1024,7 +966,7 @@ insns_match_p (int mode ATTRIBUTE_UNUSED, rtx i1, rtx i2)
 
   if (CALL_P (i1)
       && (!rtx_equal_p (CALL_INSN_FUNCTION_USAGE (i1),
-                       CALL_INSN_FUNCTION_USAGE (i2))
+                       CALL_INSN_FUNCTION_USAGE (i2))
          || SIBLING_CALL_P (i1) != SIBLING_CALL_P (i2)))
     return false;
 
@@ -1036,8 +978,8 @@ insns_match_p (int mode ATTRIBUTE_UNUSED, rtx i1, rtx i2)
   if ((mode & CLEANUP_POST_REGSTACK) && stack_regs_mentioned (i1))
     {
       /* If register stack conversion has already been done, then
-         death notes must also be compared before it is certain that
-         the two instruction streams match.  */
+        death notes must also be compared before it is certain that
+        the two instruction streams match.  */
 
       rtx note;
       HARD_REG_SET i1_regset, i2_regset;
@@ -1152,7 +1094,7 @@ flow_find_cross_jump (int mode ATTRIBUTE_UNUSED, basic_block bb1,
       if (i1 == BB_HEAD (bb1) || i2 == BB_HEAD (bb2))
        break;
 
-      if (!insns_match_p (mode, i1, i2))
+      if (!old_insns_match_p (mode, i1, i2))
        break;
 
       merge_memattrs (i1, i2);
@@ -1216,6 +1158,134 @@ flow_find_cross_jump (int mode ATTRIBUTE_UNUSED, basic_block bb1,
   return ninsns;
 }
 
+/* Return true iff the condbranches at the end of BB1 and BB2 match.  */
+bool
+condjump_equiv_p (struct equiv_info *info, bool call_init)
+{
+  basic_block bb1 = info->x_block;
+  basic_block bb2 = info->y_block;
+  edge b1 = BRANCH_EDGE (bb1);
+  edge b2 = BRANCH_EDGE (bb2);
+  edge f1 = FALLTHRU_EDGE (bb1);
+  edge f2 = FALLTHRU_EDGE (bb2);
+  bool reverse, match;
+  rtx set1, set2, cond1, cond2;
+  rtx src1, src2;
+  enum rtx_code code1, code2;
+
+  /* Get around possible forwarders on fallthru edges.  Other cases
+     should be optimized out already.  */
+  if (FORWARDER_BLOCK_P (f1->dest))
+    f1 = single_succ_edge (f1->dest);
+
+  if (FORWARDER_BLOCK_P (f2->dest))
+    f2 = single_succ_edge (f2->dest);
+
+  /* To simplify use of this function, return false if there are
+     unneeded forwarder blocks.  These will get eliminated later
+     during cleanup_cfg.  */
+  if (FORWARDER_BLOCK_P (f1->dest)
+      || FORWARDER_BLOCK_P (f2->dest)
+      || FORWARDER_BLOCK_P (b1->dest)
+      || FORWARDER_BLOCK_P (b2->dest))
+    return false;
+
+  if (f1->dest == f2->dest && b1->dest == b2->dest)
+    reverse = false;
+  else if (f1->dest == b2->dest && b1->dest == f2->dest)
+    reverse = true;
+  else
+    return false;
+
+  set1 = pc_set (BB_END (bb1));
+  set2 = pc_set (BB_END (bb2));
+  if ((XEXP (SET_SRC (set1), 1) == pc_rtx)
+      != (XEXP (SET_SRC (set2), 1) == pc_rtx))
+    reverse = !reverse;
+
+  src1 = SET_SRC (set1);
+  src2 = SET_SRC (set2);
+  cond1 = XEXP (src1, 0);
+  cond2 = XEXP (src2, 0);
+  code1 = GET_CODE (cond1);
+  if (reverse)
+    code2 = reversed_comparison_code (cond2, BB_END (bb2));
+  else
+    code2 = GET_CODE (cond2);
+
+  if (code2 == UNKNOWN)
+    return false;
+
+  if (call_init && !struct_equiv_init (STRUCT_EQUIV_START | info->mode, info))
+    gcc_unreachable ();
+  /* Make the sources of the pc sets unreadable so that when we call
+     insns_match_p it won't process them.
+     The death_notes_match_p from insns_match_p won't see the local registers
+     used for the pc set, but that could only cause missed optimizations when
+     there are actually condjumps that use stack registers.  */
+  SET_SRC (set1) = pc_rtx;
+  SET_SRC (set2) = pc_rtx;
+  /* Verify codes and operands match.  */
+  if (code1 == code2)
+    {
+      match = (insns_match_p (BB_END (bb1), BB_END (bb2), info)
+              && rtx_equiv_p (&XEXP (cond1, 0), XEXP (cond2, 0), 1, info)
+              && rtx_equiv_p (&XEXP (cond1, 1), XEXP (cond2, 1), 1, info));
+
+    }
+  else if (code1 == swap_condition (code2))
+    {
+      match = (insns_match_p (BB_END (bb1), BB_END (bb2), info)
+              && rtx_equiv_p (&XEXP (cond1, 1), XEXP (cond2, 0), 1, info)
+              && rtx_equiv_p (&XEXP (cond1, 0), XEXP (cond2, 1), 1, info));
+
+    }
+  else
+    match = false;
+  SET_SRC (set1) = src1;
+  SET_SRC (set2) = src2;
+  match &= verify_changes (0);
+
+  /* If we return true, we will join the blocks.  Which means that
+     we will only have one branch prediction bit to work with.  Thus
+     we require the existing branches to have probabilities that are
+     roughly similar.  */
+  if (match
+      && !optimize_size
+      && maybe_hot_bb_p (bb1)
+      && maybe_hot_bb_p (bb2))
+    {
+      int prob2;
+
+      if (b1->dest == b2->dest)
+       prob2 = b2->probability;
+      else
+       /* Do not use f2 probability as f2 may be forwarded.  */
+       prob2 = REG_BR_PROB_BASE - b2->probability;
+
+      /* Fail if the difference in probabilities is greater than 50%.
+        This rules out two well-predicted branches with opposite
+        outcomes.  */
+      if (abs (b1->probability - prob2) > REG_BR_PROB_BASE / 2)
+       {
+         if (dump_file)
+           fprintf (dump_file,
+                    "Outcomes of branch in bb %i and %i differ too much (%i %i)\n",
+                    bb1->index, bb2->index, b1->probability, prob2);
+
+         match = false;
+       }
+    }
+
+  if (dump_file && match)
+    fprintf (dump_file, "Conditionals in bb %i and %i match.\n",
+            bb1->index, bb2->index);
+
+  if (!match)
+    cancel_changes (0);
+  return match;
+}
+
 /* Return true iff outgoing edges of BB1 and BB2 match, together with
    the branch instruction.  This means that if we commonize the control
    flow before end of the basic block, the semantic remains unchanged.
@@ -1232,11 +1302,12 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
 
   /* If BB1 has only one successor, we may be looking at either an
      unconditional jump, or a fake edge to exit.  */
-  if (EDGE_COUNT (bb1->succs) == 1
-      && (EDGE_SUCC (bb1, 0)->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0
+  if (single_succ_p (bb1)
+      && (single_succ_edge (bb1)->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0
       && (!JUMP_P (BB_END (bb1)) || simplejump_p (BB_END (bb1))))
-    return (EDGE_COUNT (bb2->succs) == 1
-           && (EDGE_SUCC (bb2, 0)->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0
+    return (single_succ_p (bb2)
+           && (single_succ_edge (bb2)->flags
+               & (EDGE_COMPLEX | EDGE_FAKE)) == 0
            && (!JUMP_P (BB_END (bb2)) || simplejump_p (BB_END (bb2))));
 
   /* Match conditional jumps - this may get tricky when fallthru and branch
@@ -1261,12 +1332,12 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
       f2 = FALLTHRU_EDGE (bb2);
 
       /* Get around possible forwarders on fallthru edges.  Other cases
-         should be optimized out already.  */
+        should be optimized out already.  */
       if (FORWARDER_BLOCK_P (f1->dest))
-       f1 = EDGE_SUCC (f1->dest, 0);
+       f1 = single_succ_edge (f1->dest);
 
       if (FORWARDER_BLOCK_P (f2->dest))
-       f2 = EDGE_SUCC (f2->dest, 0);
+       f2 = single_succ_edge (f2->dest);
 
       /* To simplify use of this function, return false if there are
         unneeded forwarder blocks.  These will get eliminated later
@@ -1335,7 +1406,7 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
            {
              if (dump_file)
                fprintf (dump_file,
-                        "Outcomes of branch in bb %i and %i differs to much (%i %i)\n",
+                        "Outcomes of branch in bb %i and %i differ too much (%i %i)\n",
                         bb1->index, bb2->index, b1->probability, prob2);
 
              return false;
@@ -1352,7 +1423,6 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
   /* Generic case - we are seeing a computed jump, table jump or trapping
      instruction.  */
 
-#ifndef CASE_DROPS_THROUGH
   /* Check whether there are tablejumps in the end of BB1 and BB2.
      Return true if they are identical.  */
     {
@@ -1407,7 +1477,7 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
                  rr.update_label_nuses = false;
                  for_each_rtx (&BB_END (bb1), replace_label, &rr);
 
-                 match = insns_match_p (mode, BB_END (bb1), BB_END (bb2));
+                 match = old_insns_match_p (mode, BB_END (bb1), BB_END (bb2));
                  if (dump_file && match)
                    fprintf (dump_file,
                             "Tablejumps in bb %i and %i match.\n",
@@ -1426,11 +1496,10 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
          return false;
        }
     }
-#endif
 
   /* First ensure that the instructions match.  There may be many outgoing
      edges so this test is generally cheaper.  */
-  if (!insns_match_p (mode, BB_END (bb1), BB_END (bb2)))
+  if (!old_insns_match_p (mode, BB_END (bb1), BB_END (bb2)))
     return false;
 
   /* Search the outgoing edges, ensure that the counts do match, find possible
@@ -1442,7 +1511,7 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
   FOR_EACH_EDGE (e1, ei, bb1->succs)
     {
       e2 = EDGE_SUCC (bb2, ei.index);
-      
+
       if (e1->flags & EDGE_EH)
        nehedges1++;
 
@@ -1464,9 +1533,9 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
   if (fallthru1)
     {
       basic_block d1 = (forwarder_block_p (fallthru1->dest)
-                       ? EDGE_SUCC (fallthru1->dest, 0)->dest: fallthru1->dest);
+                       ? single_succ (fallthru1->dest): fallthru1->dest);
       basic_block d2 = (forwarder_block_p (fallthru2->dest)
-                       ? EDGE_SUCC (fallthru2->dest, 0)->dest: fallthru2->dest);
+                       ? single_succ (fallthru2->dest): fallthru2->dest);
 
       if (d1 != d2)
        return false;
@@ -1484,11 +1553,43 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
       return false;
   }
 
-  /* We don't need to match the rest of edges as above checks should be enough
-     to ensure that they are equivalent.  */
+  /* The same checks as in try_crossjump_to_edge. It is required for RTL
+     version of sequence abstraction.  */
+  FOR_EACH_EDGE (e1, ei, bb2->succs)
+    {
+      edge e2;
+      edge_iterator ei;
+      basic_block d1 = e1->dest;
+
+      if (FORWARDER_BLOCK_P (d1))
+        d1 = EDGE_SUCC (d1, 0)->dest;
+
+      FOR_EACH_EDGE (e2, ei, bb1->succs)
+        {
+          basic_block d2 = e2->dest;
+          if (FORWARDER_BLOCK_P (d2))
+            d2 = EDGE_SUCC (d2, 0)->dest;
+          if (d1 == d2)
+            break;
+        }
+
+      if (!e2)
+        return false;
+    }
+
   return true;
 }
 
+/* Returns true if BB basic block has a preserve label.  */
+
+static bool
+block_has_preserve_label (basic_block bb)
+{
+  return (bb
+          && block_label (bb)
+          && LABEL_PRESERVE_P (block_label (bb)));
+}
+
 /* E1 and E2 are edges with the same destination block.  Search their
    predecessors for common code.  If found, redirect control flow from
    (maybe the middle of) E1->SRC to (maybe the middle of) E2->SRC.  */
@@ -1506,12 +1607,12 @@ try_crossjump_to_edge (int mode, edge e1, edge e2)
   newpos1 = newpos2 = NULL_RTX;
 
   /* If we have partitioned hot/cold basic blocks, it is a bad idea
-     to try this optimization. 
+     to try this optimization.
 
      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 (flag_reorder_blocks_and_partition && no_new_pseudos)
@@ -1521,13 +1622,13 @@ try_crossjump_to_edge (int mode, edge e1, edge e2)
      about multiple entry or chained forwarders, as they will be optimized
      away.  We do this to look past the unconditional jump following a
      conditional jump that is required due to the current CFG shape.  */
-  if (EDGE_COUNT (src1->preds) == 1
+  if (single_pred_p (src1)
       && FORWARDER_BLOCK_P (src1))
-    e1 = EDGE_PRED (src1, 0), src1 = e1->src;
+    e1 = single_pred_edge (src1), src1 = e1->src;
 
-  if (EDGE_COUNT (src2->preds) == 1
+  if (single_pred_p (src2)
       && FORWARDER_BLOCK_P (src2))
-    e2 = EDGE_PRED (src2, 0), src2 = e2->src;
+    e2 = single_pred_edge (src2), src2 = e2->src;
 
   /* Nothing to do if we reach ENTRY, or a common source block.  */
   if (src1 == ENTRY_BLOCK_PTR || src2 == ENTRY_BLOCK_PTR)
@@ -1537,11 +1638,11 @@ try_crossjump_to_edge (int mode, edge e1, edge e2)
 
   /* Seeing more than 1 forwarder blocks would confuse us later...  */
   if (FORWARDER_BLOCK_P (e1->dest)
-      && FORWARDER_BLOCK_P (EDGE_SUCC (e1->dest, 0)->dest))
+      && FORWARDER_BLOCK_P (single_succ (e1->dest)))
     return false;
 
   if (FORWARDER_BLOCK_P (e2->dest)
-      && FORWARDER_BLOCK_P (EDGE_SUCC (e2->dest, 0)->dest))
+      && FORWARDER_BLOCK_P (single_succ (e2->dest)))
     return false;
 
   /* Likewise with dead code (possibly newly created by the other optimizations
@@ -1564,7 +1665,11 @@ try_crossjump_to_edge (int mode, edge e1, edge e2)
       && (newpos1 != BB_HEAD (src1)))
     return false;
 
-#ifndef CASE_DROPS_THROUGH
+  /* Avoid deleting preserve label when redirecting ABNORMAL edges.  */
+  if (block_has_preserve_label (e1->dest)
+      && (e1->flags & EDGE_ABNORMAL))
+    return false;
+
   /* Here we know that the insns in the end of SRC1 which are common with SRC2
      will be deleted.
      If we have tablejumps in the end of SRC1 and SRC2
@@ -1595,13 +1700,24 @@ try_crossjump_to_edge (int mode, edge e1, edge e2)
            }
        }
     }
-#endif
 
-  /* Avoid splitting if possible.  */
-  if (newpos2 == BB_HEAD (src2))
+  /* Avoid splitting if possible.  We must always split when SRC2 has
+     EH predecessor edges, or we may end up with basic blocks with both
+     normal and EH predecessor edges.  */
+  if (newpos2 == BB_HEAD (src2)
+      && !(EDGE_PRED (src2, 0)->flags & EDGE_EH))
     redirect_to = src2;
   else
     {
+      if (newpos2 == BB_HEAD (src2))
+       {
+         /* Skip possible basic block header.  */
+         if (LABEL_P (newpos2))
+           newpos2 = NEXT_INSN (newpos2);
+         if (NOTE_P (newpos2))
+           newpos2 = NEXT_INSN (newpos2);
+       }
+
       if (dump_file)
        fprintf (dump_file, "Splitting bb %i before %i insns\n",
                 src2->index, nmatch);
@@ -1615,7 +1731,7 @@ try_crossjump_to_edge (int mode, edge e1, edge e2)
 
   redirect_to->count += src1->count;
   redirect_to->frequency += src1->frequency;
-  /* We may have some registers visible trought the block.  */
+  /* We may have some registers visible through the block.  */
   redirect_to->flags |= BB_DIRTY;
 
   /* Recompute the frequencies and counts of outgoing edges.  */
@@ -1626,13 +1742,13 @@ try_crossjump_to_edge (int mode, edge e1, edge e2)
       basic_block d = s->dest;
 
       if (FORWARDER_BLOCK_P (d))
-       d = EDGE_SUCC (d, 0)->dest;
+       d = single_succ (d);
 
       FOR_EACH_EDGE (s2, ei, src1->succs)
        {
          basic_block d2 = s2->dest;
          if (FORWARDER_BLOCK_P (d2))
-           d2 = EDGE_SUCC (d2, 0)->dest;
+           d2 = single_succ (d2);
          if (d == d2)
            break;
        }
@@ -1640,20 +1756,20 @@ try_crossjump_to_edge (int mode, edge e1, edge e2)
       s->count += s2->count;
 
       /* Take care to update possible forwarder blocks.  We verified
-         that there is no more than one in the chain, so we can't run
-         into infinite loop.  */
+        that there is no more than one in the chain, so we can't run
+        into infinite loop.  */
       if (FORWARDER_BLOCK_P (s->dest))
        {
-         EDGE_SUCC (s->dest, 0)->count += s2->count;
+         single_succ_edge (s->dest)->count += s2->count;
          s->dest->count += s2->count;
          s->dest->frequency += EDGE_FREQUENCY (s);
        }
 
       if (FORWARDER_BLOCK_P (s2->dest))
        {
-         EDGE_SUCC (s2->dest, 0)->count -= s2->count;
-         if (EDGE_SUCC (s2->dest, 0)->count < 0)
-           EDGE_SUCC (s2->dest, 0)->count = 0;
+         single_succ_edge (s2->dest)->count -= s2->count;
+         if (single_succ_edge (s2->dest)->count < 0)
+           single_succ_edge (s2->dest)->count = 0;
          s2->dest->count -= s2->count;
          s2->dest->frequency -= EDGE_FREQUENCY (s);
          if (s2->dest->frequency < 0)
@@ -1683,12 +1799,14 @@ try_crossjump_to_edge (int mode, edge e1, edge e2)
     newpos1 = NEXT_INSN (newpos1);
 
   redirect_from = split_block (src1, PREV_INSN (newpos1))->src;
-  to_remove = EDGE_SUCC (redirect_from, 0)->dest;
+  to_remove = single_succ (redirect_from);
 
-  redirect_edge_and_branch_force (EDGE_SUCC (redirect_from, 0), redirect_to);
+  redirect_edge_and_branch_force (single_succ_edge (redirect_from), redirect_to);
   delete_basic_block (to_remove);
 
   update_forwarder_flag (redirect_from);
+  if (redirect_to != src2)
+    update_forwarder_flag (src2);
 
   return true;
 }
@@ -1710,19 +1828,26 @@ try_crossjump_bb (int mode, basic_block bb)
   if (EDGE_COUNT (bb->preds) < 2)
     return false;
 
+  /* Don't crossjump if this block ends in a computed jump,
+     unless we are optimizing for size.  */
+  if (!optimize_size
+      && bb != EXIT_BLOCK_PTR
+      && computed_jump_p (BB_END (bb)))
+    return false;
+
   /* 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 
+     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
-      && (BB_PARTITION (EDGE_PRED (bb, 0)->src) != BB_PARTITION (EDGE_PRED (bb, 1)->src)
-         || (EDGE_PRED (bb, 0)->flags & EDGE_CROSSING)))
+  if (BB_PARTITION (EDGE_PRED (bb, 0)->src) !=
+                                       BB_PARTITION (EDGE_PRED (bb, 1)->src)
+      || (EDGE_PRED (bb, 0)->flags & EDGE_CROSSING))
     return false;
 
   /* It is always cheapest to redirect a block that ends in a branch to
@@ -1737,7 +1862,7 @@ try_crossjump_bb (int mode, basic_block bb)
   FOR_EACH_EDGE (e, ei, bb->preds)
     {
       if (e->flags & EDGE_FALLTHRU)
-        fallthru = e;
+       fallthru = e;
     }
 
   changed = false;
@@ -1837,12 +1962,12 @@ try_optimize_cfg (int mode)
   if (mode & CLEANUP_CROSSJUMP)
     add_noreturn_fake_exit_edges ();
 
-  FOR_EACH_BB (bb)
-    update_forwarder_flag (bb);
-
   if (mode & (CLEANUP_UPDATE_LIFE | CLEANUP_CROSSJUMP | CLEANUP_THREADING))
     clear_bb_flags ();
 
+  FOR_EACH_BB (bb)
+    update_forwarder_flag (bb);
+
   if (! targetm.cannot_modify_jumps_p ())
     {
       first_pass = true;
@@ -1880,9 +2005,9 @@ try_optimize_cfg (int mode)
                }
 
              /* Remove code labels no longer used.  */
-             if (EDGE_COUNT (b->preds) == 1
-                 && (EDGE_PRED (b, 0)->flags & EDGE_FALLTHRU)
-                 && !(EDGE_PRED (b, 0)->flags & EDGE_COMPLEX)
+             if (single_pred_p (b)
+                 && (single_pred_edge (b)->flags & EDGE_FALLTHRU)
+                 && !(single_pred_edge (b)->flags & EDGE_COMPLEX)
                  && LABEL_P (BB_HEAD (b))
                  /* If the previous block ends with a branch to this
                     block, we can't delete the label.  Normally this
@@ -1890,10 +2015,10 @@ try_optimize_cfg (int mode)
                     if CASE_DROPS_THRU, this can be a tablejump with
                     some element going to the same place as the
                     default (fallthru).  */
-                 && (EDGE_PRED (b, 0)->src == ENTRY_BLOCK_PTR
-                     || !JUMP_P (BB_END (EDGE_PRED (b, 0)->src))
+                 && (single_pred (b) == ENTRY_BLOCK_PTR
+                     || !JUMP_P (BB_END (single_pred (b)))
                      || ! label_is_jump_target_p (BB_HEAD (b),
-                                                  BB_END (EDGE_PRED (b, 0)->src))))
+                                                  BB_END (single_pred (b)))))
                {
                  rtx label = BB_HEAD (b);
 
@@ -1914,14 +2039,14 @@ try_optimize_cfg (int mode)
 
              /* If we fall through an empty block, we can remove it.  */
              if (!(mode & CLEANUP_CFGLAYOUT)
-                 && EDGE_COUNT (b->preds) == 1
-                 && (EDGE_PRED (b, 0)->flags & EDGE_FALLTHRU)
+                 && single_pred_p (b)
+                 && (single_pred_edge (b)->flags & EDGE_FALLTHRU)
                  && !LABEL_P (BB_HEAD (b))
                  && FORWARDER_BLOCK_P (b)
                  /* Note that forwarder_block_p true ensures that
                     there is a successor for this block.  */
-                 && (EDGE_SUCC (b, 0)->flags & EDGE_FALLTHRU)
-                 && n_basic_blocks > 1)
+                 && (single_succ_edge (b)->flags & EDGE_FALLTHRU)
+                 && n_basic_blocks > NUM_FIXED_BLOCKS + 1)
                {
                  if (dump_file)
                    fprintf (dump_file,
@@ -1929,17 +2054,18 @@ try_optimize_cfg (int mode)
                             b->index);
 
                  c = b->prev_bb == ENTRY_BLOCK_PTR ? b->next_bb : b->prev_bb;
-                 redirect_edge_succ_nodup (EDGE_PRED (b, 0), EDGE_SUCC (b, 0)->dest);
+                 redirect_edge_succ_nodup (single_pred_edge (b),
+                                           single_succ (b));
                  delete_basic_block (b);
                  changed = true;
                  b = c;
                }
 
-             if (EDGE_COUNT (b->succs) == 1
-                 && (s = EDGE_SUCC (b, 0))
+             if (single_succ_p (b)
+                 && (s = single_succ_edge (b))
                  && !(s->flags & EDGE_COMPLEX)
                  && (c = s->dest) != EXIT_BLOCK_PTR
-                 && EDGE_COUNT (c->preds) == 1
+                 && single_pred_p (c)
                  && b != c)
                {
                  /* When not in cfg_layout mode use code aware of reordering
@@ -1947,7 +2073,7 @@ try_optimize_cfg (int mode)
                     does not fit merge_blocks interface and is kept here in
                     hope that it will become useless once more of compiler
                     is transformed to use cfg_layout mode.  */
-                    
+
                  if ((mode & CLEANUP_CFGLAYOUT)
                      && can_merge_blocks_p (b, c))
                    {
@@ -1981,11 +2107,12 @@ try_optimize_cfg (int mode)
                 non-trivial jump instruction without side-effects, we
                 can either delete the jump entirely, or replace it
                 with a simple unconditional jump.  */
-             if (EDGE_COUNT (b->succs) == 1
-                 && EDGE_SUCC (b, 0)->dest != EXIT_BLOCK_PTR
+             if (single_succ_p (b)
+                 && single_succ (b) != EXIT_BLOCK_PTR
                  && onlyjump_p (BB_END (b))
                  && !find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX)
-                 && try_redirect_by_replacing_jump (EDGE_SUCC (b, 0), EDGE_SUCC (b, 0)->dest,
+                 && try_redirect_by_replacing_jump (single_succ_edge (b),
+                                                    single_succ (b),
                                                     (mode & CLEANUP_CFGLAYOUT) != 0))
                {
                  update_forwarder_flag (b);
@@ -2027,7 +2154,8 @@ try_optimize_cfg (int mode)
   if (mode & CLEANUP_CROSSJUMP)
     remove_fake_exit_edges ();
 
-  clear_aux_for_blocks ();
+  FOR_ALL_BB (b)
+    b->flags &= ~(BB_FORWARDER_BLOCK | BB_NONTHREADABLE_BLOCK);
 
   return changed_overall;
 }
@@ -2070,11 +2198,11 @@ merge_seq_blocks (void)
 
   for (bb = ENTRY_BLOCK_PTR->next_bb; bb != EXIT_BLOCK_PTR; )
     {
-      if (EDGE_COUNT (bb->succs) == 1
-         && can_merge_blocks_p (bb, EDGE_SUCC (bb, 0)->dest))
+      if (single_succ_p (bb)
+         && can_merge_blocks_p (bb, single_succ (bb)))
        {
          /* Merge the blocks and retry.  */
-         merge_blocks (bb, EDGE_SUCC (bb, 0)->dest);
+         merge_blocks (bb, single_succ (bb));
          changed = true;
          continue;
        }
@@ -2117,7 +2245,7 @@ cleanup_cfg (int mode)
                                                 PROP_DEATH_NOTES
                                                 | PROP_SCAN_DEAD_CODE
                                                 | PROP_KILL_DEAD_CODE
-                                                | ((mode & CLEANUP_LOG_LINKS)
+                                                | ((mode & CLEANUP_LOG_LINKS)
                                                    ? PROP_LOG_LINKS : 0)))
            break;
        }
@@ -2130,12 +2258,89 @@ cleanup_cfg (int mode)
        }
       else
        break;
-      delete_dead_jumptables ();
+
+      /* Don't call delete_dead_jumptables in cfglayout mode, because
+        that function assumes that jump tables are in the insns stream.
+        But we also don't _have_ to delete dead jumptables in cfglayout
+        mode because we shouldn't even be looking at things that are
+        not in a basic block.  Dead jumptables are cleaned up when
+        going out of cfglayout mode.  */
+      if (!(mode & CLEANUP_CFGLAYOUT))
+       delete_dead_jumptables ();
     }
 
-  /* Kill the data we won't maintain.  */
-  free_EXPR_LIST_list (&label_value_list);
   timevar_pop (TV_CLEANUP_CFG);
 
   return changed;
 }
+\f
+static unsigned int
+rest_of_handle_jump (void)
+{
+  delete_unreachable_blocks ();
+
+  if (cfun->tail_call_emit)
+    fixup_tail_calls ();
+  return 0;
+}
+
+struct tree_opt_pass pass_jump =
+{
+  "sibling",                            /* name */
+  NULL,                                 /* gate */
+  rest_of_handle_jump,                 /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_JUMP,                              /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  TODO_ggc_collect,                     /* todo_flags_start */
+  TODO_dump_func |
+  TODO_verify_flow,                     /* todo_flags_finish */
+  'i'                                   /* letter */
+};
+
+
+static unsigned int
+rest_of_handle_jump2 (void)
+{
+  delete_trivially_dead_insns (get_insns (), max_reg_num ());
+  reg_scan (get_insns (), max_reg_num ());
+  if (dump_file)
+    dump_flow_info (dump_file, dump_flags);
+  cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0)
+              | (flag_thread_jumps ? CLEANUP_THREADING : 0));
+
+  if (optimize)
+    cleanup_cfg (CLEANUP_EXPENSIVE);
+
+  /* Jump optimization, and the removal of NULL pointer checks, may
+     have reduced the number of instructions substantially.  CSE, and
+     future passes, allocate arrays whose dimensions involve the
+     maximum instruction UID, so if we can reduce the maximum UID
+     we'll save big on memory.  */
+  renumber_insns ();
+  return 0;
+}
+
+
+struct tree_opt_pass pass_jump2 =
+{
+  "jump",                               /* name */
+  NULL,                                 /* gate */
+  rest_of_handle_jump2,                        /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_JUMP,                              /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  TODO_ggc_collect,                     /* todo_flags_start */
+  TODO_dump_func,                       /* todo_flags_finish */
+  'j'                                   /* letter */
+};
+
+