bb-reorder: Split EH edges crossing partitions.
authorRichard Henderson <rth@redhat.com>
Sat, 23 Jul 2011 19:44:19 +0000 (12:44 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Sat, 23 Jul 2011 19:44:19 +0000 (12:44 -0700)
From-SVN: r176696

gcc/ChangeLog
gcc/Makefile.in
gcc/basic-block.h
gcc/bb-reorder.c
gcc/cfg.c
gcc/cfgrtl.c
gcc/except.c
gcc/except.h
gcc/tree-cfg.c

index 42bfc5ef3c6837e78330e4d832cf15cd70817fc9..560715af90c067d9911891d940193f0f1fcbbdd1 100644 (file)
@@ -1,3 +1,23 @@
+2011-07-23  Richard Henderson  <rth@redhat.com>
+
+       * basic-block.h (EDGE_PRESERVE): New.
+       (EDGE_ALL_FLAGS, EDGE_COMPLEX): Include it.
+       * bb-reorder.c: Include except.h.
+       (fix_up_crossing_landing_pad): New.
+       (find_rarely_executed_basic_blocks_and_crossing_edges): Place 
+       landing pads in the right partition.  Duplicate as necessary.
+       (partition_hot_cold_basic_blocks): Fix up DF info after
+       duplicating landing pads.
+       * cfg.c (dump_edge_info): Add crossing and preserve to bitnames.
+       * cfgrtl.c (rtl_verify_flow_info_1): Validate that EDGE_CROSSING
+       is set properly.  Validate that EH edges are not CROSSING.
+       * except.c (expand_dw2_landing_pad_for_region): Split out from ...
+       (dw2_build_landing_pads): ... here.
+       (convert_to_eh_region_ranges): Remove code to fixup crossing
+       landing pads.
+       * except.h (expand_dw2_landing_pad_for_region): Declare.
+       * tree-cfg.c (gimple_can_merge_blocks_p): Don't merge PRESERVE edges.
+
 2011-07-23  Richard Earnshaw  <rearnsha@arm.com>
 
        PR target/49816
index 83cfb8ceb416197cb952d957e70414170b74732e..2f8d08fedf13b365f02779cbf9fc4802d42c98b9 100644 (file)
@@ -3464,7 +3464,7 @@ bb-reorder.o : bb-reorder.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(RTL_H) $(FLAGS_H) $(TIMEVAR_H) output.h $(CFGLAYOUT_H) $(FIBHEAP_H) \
    $(TARGET_H) $(FUNCTION_H) $(TM_P_H) $(OBSTACK_H) $(EXPR_H) $(REGS_H) \
    $(PARAMS_H) toplev.h $(DIAGNOSTIC_CORE_H) $(TREE_PASS_H) $(DF_H) \
-   bb-reorder.h
+   $(EXCEPT_H) bb-reorder.h
 tracer.o : tracer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    $(TREE_H) $(BASIC_BLOCK_H) hard-reg-set.h output.h $(CFGLAYOUT_H) \
    $(FLAGS_H) $(TIMEVAR_H) $(PARAMS_H) $(COVERAGE_H) $(FIBHEAP_H) \
index 29c1167cfe77fa12039d665baf68bc096fbbd3ee..c03129c6abfa62375620ad8190e7cea1689ae5c0 100644 (file)
@@ -65,31 +65,34 @@ DEF_VEC_P(edge);
 DEF_VEC_ALLOC_P(edge,gc);
 DEF_VEC_ALLOC_P(edge,heap);
 
-#define EDGE_FALLTHRU          1       /* 'Straight line' flow */
-#define EDGE_ABNORMAL          2       /* Strange flow, like computed
+/* Always update the table in cfg.c dump_edge_info.  */
+#define EDGE_FALLTHRU          0x0001  /* 'Straight line' flow */
+#define EDGE_ABNORMAL          0x0002  /* Strange flow, like computed
                                           label, or eh */
-#define EDGE_ABNORMAL_CALL     4       /* Call with abnormal exit
+#define EDGE_ABNORMAL_CALL     0x0004  /* Call with abnormal exit
                                           like an exception, or sibcall */
-#define EDGE_EH                        8       /* Exception throw */
-#define EDGE_FAKE              16      /* Not a real edge (profile.c) */
-#define EDGE_DFS_BACK          32      /* A backwards edge */
-#define EDGE_CAN_FALLTHRU      64      /* Candidate for straight line
+#define EDGE_EH                        0x0008  /* Exception throw */
+#define EDGE_FAKE              0x0010  /* Not a real edge (profile.c) */
+#define EDGE_DFS_BACK          0x0020  /* A backwards edge */
+#define EDGE_CAN_FALLTHRU      0x0040  /* Candidate for straight line
                                           flow.  */
-#define EDGE_IRREDUCIBLE_LOOP  128     /* Part of irreducible loop.  */
-#define EDGE_SIBCALL           256     /* Edge from sibcall to exit.  */
-#define EDGE_LOOP_EXIT         512     /* Exit of a loop.  */
-#define EDGE_TRUE_VALUE                1024    /* Edge taken when controlling
+#define EDGE_IRREDUCIBLE_LOOP  0x0080  /* Part of irreducible loop.  */
+#define EDGE_SIBCALL           0x0100  /* Edge from sibcall to exit.  */
+#define EDGE_LOOP_EXIT         0x0200  /* Exit of a loop.  */
+#define EDGE_TRUE_VALUE                0x0400  /* Edge taken when controlling
                                           predicate is nonzero.  */
-#define EDGE_FALSE_VALUE       2048    /* Edge taken when controlling
+#define EDGE_FALSE_VALUE       0x0800  /* Edge taken when controlling
                                           predicate is zero.  */
-#define EDGE_EXECUTABLE                4096    /* Edge is executable.  Only
+#define EDGE_EXECUTABLE                0x1000  /* Edge is executable.  Only
                                           valid during SSA-CCP.  */
-#define EDGE_CROSSING          8192    /* Edge crosses between hot
+#define EDGE_CROSSING          0x2000  /* Edge crosses between hot
                                           and cold sections, when we
                                           do partitioning.  */
-#define EDGE_ALL_FLAGS        16383
+#define EDGE_PRESERVE          0x4000  /* Never merge blocks via this edge. */
+#define EDGE_ALL_FLAGS         0x7fff
 
-#define EDGE_COMPLEX   (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH)
+#define EDGE_COMPLEX \
+  (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH | EDGE_PRESERVE)
 
 /* Counter summary from the last set of coverage counts read by
    profile.c.  */
@@ -203,7 +206,9 @@ DEF_VEC_ALLOC_P(basic_block,heap);
    the compilation, so they are never cleared.
 
    All other flags may be cleared by clear_bb_flags().  It is generally
-   a bad idea to rely on any flags being up-to-date.  */
+   a bad idea to rely on any flags being up-to-date.
+
+   Always update the table in cfg.c dump_bb_info.  */
 
 enum bb_flags
 {
index 763cbe5174156f8a4044b8a78af4f60efa5ddb55..11423fed29a0985295dd0112f06622ad83b32f41 100644 (file)
@@ -87,6 +87,7 @@
 #include "tree-pass.h"
 #include "df.h"
 #include "bb-reorder.h"
+#include "except.h"
 
 /* The number of rounds.  In most cases there will only be 4 rounds, but
    when partitioning hot and cold basic blocks into separate sections of
@@ -1208,6 +1209,79 @@ get_uncond_jump_length (void)
   return length;
 }
 
+/* Emit a barrier into the footer of BB.  */
+
+static void
+emit_barrier_after_bb (basic_block bb)
+{
+  rtx barrier = emit_barrier_after (BB_END (bb));
+  bb->il.rtl->footer = unlink_insn_chain (barrier, barrier);
+}
+
+/* The landing pad OLD_LP, in block OLD_BB, has edges from both partitions.
+   Duplicate the landing pad and split the edges so that no EH edge
+   crosses partitions.  */
+
+static void
+fix_up_crossing_landing_pad (eh_landing_pad old_lp, basic_block old_bb)
+{
+  eh_landing_pad new_lp;
+  basic_block new_bb, last_bb, post_bb;
+  rtx new_label, jump, post_label;
+  unsigned new_partition;
+  edge_iterator ei;
+  edge e;
+
+  /* Generate the new landing-pad structure.  */
+  new_lp = gen_eh_landing_pad (old_lp->region);
+  new_lp->post_landing_pad = old_lp->post_landing_pad;
+  new_lp->landing_pad = gen_label_rtx ();
+  LABEL_PRESERVE_P (new_lp->landing_pad) = 1;
+
+  /* Put appropriate instructions in new bb.  */
+  new_label = emit_label (new_lp->landing_pad);
+
+  expand_dw2_landing_pad_for_region (old_lp->region);
+
+  post_bb = BLOCK_FOR_INSN (old_lp->landing_pad);
+  post_bb = single_succ (post_bb);
+  post_label = block_label (post_bb);
+  jump = emit_jump_insn (gen_jump (post_label));
+  JUMP_LABEL (jump) = post_label;
+
+  /* Create new basic block to be dest for lp.  */
+  last_bb = EXIT_BLOCK_PTR->prev_bb;
+  new_bb = create_basic_block (new_label, jump, last_bb);
+  new_bb->aux = last_bb->aux;
+  last_bb->aux = new_bb;
+
+  emit_barrier_after_bb (new_bb);
+
+  make_edge (new_bb, post_bb, 0);
+
+  /* Make sure new bb is in the other partition.  */
+  new_partition = BB_PARTITION (old_bb);
+  new_partition ^= BB_HOT_PARTITION | BB_COLD_PARTITION;
+  BB_SET_PARTITION (new_bb, new_partition);
+
+  /* Fix up the edges.  */
+  for (ei = ei_start (old_bb->preds); (e = ei_safe_edge (ei)) != NULL; )
+    if (BB_PARTITION (e->src) == new_partition)
+      {
+       rtx insn = BB_END (e->src);
+       rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+
+       gcc_assert (note != NULL);
+       gcc_checking_assert (INTVAL (XEXP (note, 0)) == old_lp->index);
+       XEXP (note, 0) = GEN_INT (new_lp->index);
+
+       /* Adjust the edge to the new destination.  */
+       redirect_edge_succ (e, new_bb);
+      }
+    else
+      ei_next (&ei);
+}
+
 /* Find the basic blocks that are rarely executed and need to be moved to
    a separate section of the .o file (to cut down on paging and improve
    cache locality).  Return a vector of all edges that cross.  */
@@ -1221,7 +1295,6 @@ find_rarely_executed_basic_blocks_and_crossing_edges (void)
   edge_iterator ei;
 
   /* Mark which partition (hot/cold) each basic block belongs in.  */
-
   FOR_EACH_BB (bb)
     {
       if (probably_never_executed_bb_p (bb))
@@ -1230,32 +1303,71 @@ find_rarely_executed_basic_blocks_and_crossing_edges (void)
        BB_SET_PARTITION (bb, BB_HOT_PARTITION);
     }
 
-  /* Mark every edge that crosses between sections.  */
-
-  FOR_EACH_BB (bb)
-    FOR_EACH_EDGE (e, ei, bb->succs)
+  /* The format of .gcc_except_table does not allow landing pads to
+     be in a different partition as the throw.  Fix this by either
+     moving or duplicating the landing pads.  */
+  if (cfun->eh->lp_array)
     {
-      if (e->src != ENTRY_BLOCK_PTR
-         && e->dest != EXIT_BLOCK_PTR
-         && BB_PARTITION (e->src) != BB_PARTITION (e->dest))
+      unsigned i;
+      eh_landing_pad lp;
+
+      FOR_EACH_VEC_ELT (eh_landing_pad, cfun->eh->lp_array, i, lp)
        {
-         e->flags |= EDGE_CROSSING;
-         VEC_safe_push (edge, heap, crossing_edges, e);
+         bool all_same, all_diff;
+
+         if (lp == NULL)
+           continue;
+
+         all_same = all_diff = true;
+         bb = BLOCK_FOR_INSN (lp->landing_pad);
+         FOR_EACH_EDGE (e, ei, bb->preds)
+           {
+             gcc_assert (e->flags & EDGE_EH);
+             if (BB_PARTITION (bb) == BB_PARTITION (e->src))
+               all_diff = false;
+             else
+               all_same = false;
+           }
+
+         if (all_same)
+           ;
+         else if (all_diff)
+           {
+             int which = BB_PARTITION (bb);
+             which ^= BB_HOT_PARTITION | BB_COLD_PARTITION;
+             BB_SET_PARTITION (bb, which);
+           }
+         else
+           fix_up_crossing_landing_pad (lp, bb);
        }
-      else
-       e->flags &= ~EDGE_CROSSING;
     }
 
-  return crossing_edges;
-}
+  /* Mark every edge that crosses between sections.  */
 
-/* Emit a barrier into the footer of BB.  */
+  FOR_EACH_BB (bb)
+    FOR_EACH_EDGE (e, ei, bb->succs)
+      {
+       unsigned int flags = e->flags;
+      
+        /* We should never have EDGE_CROSSING set yet.  */
+       gcc_checking_assert ((flags & EDGE_CROSSING) == 0);
+
+       if (e->src != ENTRY_BLOCK_PTR
+           && e->dest != EXIT_BLOCK_PTR
+           && BB_PARTITION (e->src) != BB_PARTITION (e->dest))
+         {
+           VEC_safe_push (edge, heap, crossing_edges, e);
+           flags |= EDGE_CROSSING;
+         }
 
-static void
-emit_barrier_after_bb (basic_block bb)
-{
-  rtx barrier = emit_barrier_after (BB_END (bb));
-  bb->il.rtl->footer = unlink_insn_chain (barrier, barrier);
+       /* Now that we've split eh edges as appropriate, allow landing pads
+          to be merged with the post-landing pads.  */
+       flags &= ~EDGE_PRESERVE;
+
+       e->flags = flags;
+      }
+
+  return crossing_edges;
 }
 
 /* If any destination of a crossing edge does not have a label, add label;
@@ -2108,6 +2220,8 @@ partition_hot_cold_basic_blocks (void)
   if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1)
     return 0;
 
+  df_set_flags (DF_DEFER_INSN_RESCAN);
+
   crossing_edges = find_rarely_executed_basic_blocks_and_crossing_edges ();
   if (crossing_edges == NULL)
     return 0;
@@ -2139,6 +2253,38 @@ partition_hot_cold_basic_blocks (void)
 
   VEC_free (edge, heap, crossing_edges);
 
+  /* ??? FIXME: DF generates the bb info for a block immediately.
+     And by immediately, I mean *during* creation of the block.
+
+       #0  df_bb_refs_collect
+       #1  in df_bb_refs_record
+       #2  in create_basic_block_structure
+
+     Which means that the bb_has_eh_pred test in df_bb_refs_collect
+     will *always* fail, because no edges can have been added to the
+     block yet.  Which of course means we don't add the right 
+     artificial refs, which means we fail df_verify (much) later.
+
+     Cleanest solution would seem to make DF_DEFER_INSN_RESCAN imply
+     that we also shouldn't grab data from the new blocks those new
+     insns are in either.  In this way one can create the block, link
+     it up properly, and have everything Just Work later, when deferred
+     insns are processed.
+
+     In the meantime, we have no other option but to throw away all
+     of the DF data and recompute it all.  */
+  if (cfun->eh->lp_array)
+    {
+      df_finish_pass (true);
+      df_scan_alloc (NULL);
+      df_scan_blocks ();
+      /* Not all post-landing pads use all of the EH_RETURN_DATA_REGNO
+        data.  We blindly generated all of them when creating the new
+        landing pad.  Delete those assignments we don't use.  */
+      df_set_flags (DF_LR_RUN_DCE);
+      df_analyze ();
+    }
+
   return TODO_verify_flow | TODO_verify_rtl_sharing;
 }
 \f
index 00d1d5cb7d8e5fee548cf6c1886232d6c6fec33b..ca04c94770e71f2c789e60aa85ffc7ca2e31271e 100644 (file)
--- a/gcc/cfg.c
+++ b/gcc/cfg.c
@@ -720,7 +720,7 @@ dump_edge_info (FILE *file, edge e, int do_succ)
       static const char * const bitnames[] = {
        "fallthru", "ab", "abcall", "eh", "fake", "dfs_back",
        "can_fallthru", "irreducible", "sibcall", "loop_exit",
-       "true", "false", "exec"
+       "true", "false", "exec", "crossing", "preserve"
       };
       int comma = 0;
       int i, flags = e->flags;
index b8843cae579537a0dcd891da12b72f144b6cd808..076ff03d056cd46eb9b93a7ed1c75cf04c02753b 100644 (file)
@@ -1820,18 +1820,38 @@ rtl_verify_flow_info_1 (void)
        }
       FOR_EACH_EDGE (e, ei, bb->succs)
        {
+         bool is_crossing;
+
          if (e->flags & EDGE_FALLTHRU)
+           n_fallthru++, fallthru = e;
+
+         is_crossing = (BB_PARTITION (e->src) != BB_PARTITION (e->dest)
+                        && e->src != ENTRY_BLOCK_PTR
+                        && e->dest != EXIT_BLOCK_PTR);
+         if (e->flags & EDGE_CROSSING)
            {
-             n_fallthru++, fallthru = e;
-             if ((e->flags & EDGE_CROSSING)
-                 || (BB_PARTITION (e->src) != BB_PARTITION (e->dest)
-                     && e->src != ENTRY_BLOCK_PTR
-                     && e->dest != EXIT_BLOCK_PTR))
-           {
+             if (!is_crossing)
+               {
+                 error ("EDGE_CROSSING incorrectly set across same section");
+                 err = 1;
+               }
+             if (e->flags & EDGE_FALLTHRU)
+               {
                  error ("fallthru edge crosses section boundary (bb %i)",
                         e->src->index);
                  err = 1;
                }
+             if (e->flags & EDGE_EH)
+               {
+                 error ("EH edge crosses section boundary (bb %i)",
+                        e->src->index);
+                 err = 1;
+               }
+           }
+         else if (is_crossing)
+           {
+             error ("EDGE_CROSSING missing across section boundary");
+             err = 1;
            }
 
          if ((e->flags & ~(EDGE_DFS_BACK
index bb16036d3618de4b07f6a8142f898ac189a9366a..8d56e105fbee8896a1e66b8c64b621f753825428 100644 (file)
@@ -919,6 +919,34 @@ emit_to_new_bb_before (rtx seq, rtx insn)
   return bb;
 }
 \f
+/* A subroutine of dw2_build_landing_pads, also used for edge splitting
+   at the rtl level.  Emit the code required by the target at a landing
+   pad for the given region.  */
+
+void
+expand_dw2_landing_pad_for_region (eh_region region)
+{
+#ifdef HAVE_exception_receiver
+  if (HAVE_exception_receiver)
+    emit_insn (gen_exception_receiver ());
+  else
+#endif
+#ifdef HAVE_nonlocal_goto_receiver
+  if (HAVE_nonlocal_goto_receiver)
+    emit_insn (gen_nonlocal_goto_receiver ());
+  else
+#endif
+    { /* Nothing */ }
+
+  if (region->exc_ptr_reg)
+    emit_move_insn (region->exc_ptr_reg,
+                   gen_rtx_REG (ptr_mode, EH_RETURN_DATA_REGNO (0)));
+  if (region->filter_reg)
+    emit_move_insn (region->filter_reg,
+                   gen_rtx_REG (targetm.eh_return_filter_mode (),
+                                EH_RETURN_DATA_REGNO (1)));
+}
+
 /* Expand the extra code needed at landing pads for dwarf2 unwinding.  */
 
 static void
@@ -926,10 +954,17 @@ dw2_build_landing_pads (void)
 {
   int i;
   eh_landing_pad lp;
+  int e_flags = EDGE_FALLTHRU;
+
+  /* If we're going to partition blocks, we need to be able to add
+     new landing pads later, which means that we need to hold on to
+     the post-landing-pad block.  Prevent it from being merged away.
+     We'll remove this bit after partitioning.  */
+  if (flag_reorder_blocks_and_partition)
+    e_flags |= EDGE_PRESERVE;
 
   for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i)
     {
-      eh_region region;
       basic_block bb;
       rtx seq;
       edge e;
@@ -943,32 +978,13 @@ dw2_build_landing_pads (void)
       emit_label (lp->landing_pad);
       LABEL_PRESERVE_P (lp->landing_pad) = 1;
 
-#ifdef HAVE_exception_receiver
-      if (HAVE_exception_receiver)
-       emit_insn (gen_exception_receiver ());
-      else
-#endif
-#ifdef HAVE_nonlocal_goto_receiver
-       if (HAVE_nonlocal_goto_receiver)
-         emit_insn (gen_nonlocal_goto_receiver ());
-       else
-#endif
-         { /* Nothing */ }
-
-      region = lp->region;
-      if (region->exc_ptr_reg)
-       emit_move_insn (region->exc_ptr_reg,
-                       gen_rtx_REG (ptr_mode, EH_RETURN_DATA_REGNO (0)));
-      if (region->filter_reg)
-       emit_move_insn (region->filter_reg,
-                       gen_rtx_REG (targetm.eh_return_filter_mode (),
-                                    EH_RETURN_DATA_REGNO (1)));
+      expand_dw2_landing_pad_for_region (lp->region);
 
       seq = get_insns ();
       end_sequence ();
 
       bb = emit_to_new_bb_before (seq, label_rtx (lp->post_landing_pad));
-      e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
+      e = make_edge (bb, bb->next_bb, e_flags);
       e->count = bb->count;
       e->probability = REG_BR_PROB_BASE;
     }
@@ -2388,9 +2404,6 @@ convert_to_eh_region_ranges (void)
   rtx section_switch_note = NULL_RTX;
   rtx first_no_action_insn_before_switch = NULL_RTX;
   rtx last_no_action_insn_before_switch = NULL_RTX;
-  rtx *pad_map = NULL;
-  sbitmap pad_loc = NULL;
-  int min_labelno = 0, max_labelno = 0;
   int saved_call_site_base = call_site_base;
 
   crtl->eh.action_record_data = VEC_alloc (uchar, gc, 64);
@@ -2523,13 +2536,7 @@ convert_to_eh_region_ranges (void)
        gcc_assert (crtl->eh.call_site_record[cur_sec] == NULL);
        crtl->eh.call_site_record[cur_sec]
          = VEC_alloc (call_site_record, gc, 10);
-       max_labelno = max_label_num ();
-       min_labelno = get_first_label_num ();
-       pad_map = XCNEWVEC (rtx, max_labelno - min_labelno + 1);
-       pad_loc = sbitmap_alloc (max_labelno - min_labelno + 1);
       }
-    else if (LABEL_P (iter) && pad_map)
-      SET_BIT (pad_loc, CODE_LABEL_NUMBER (iter) - min_labelno);
 
   if (last_action >= -1 && ! first_no_action_insn)
     {
@@ -2539,103 +2546,6 @@ convert_to_eh_region_ranges (void)
 
   call_site_base = saved_call_site_base;
 
-  if (pad_map)
-    {
-      /* When doing hot/cold partitioning, ensure landing pads are
-        always in the same section as the EH region, .gcc_except_table
-        can't express it otherwise.  */
-      for (cur_sec = 0; cur_sec < 2; cur_sec++)
-       {
-         int i, idx;
-         int n = VEC_length (call_site_record,
-                             crtl->eh.call_site_record[cur_sec]);
-         basic_block prev_bb = NULL, padbb;
-
-         for (i = 0; i < n; ++i)
-           {
-             struct call_site_record_d *cs =
-               VEC_index (call_site_record,
-                          crtl->eh.call_site_record[cur_sec], i);
-             rtx jump, note;
-
-             if (cs->landing_pad == NULL_RTX)
-               continue;
-             idx = CODE_LABEL_NUMBER (cs->landing_pad) - min_labelno;
-             /* If the landing pad is in the correct section, nothing
-                is needed.  */
-             if (TEST_BIT (pad_loc, idx) ^ (cur_sec == 0))
-               continue;
-             /* Otherwise, if we haven't seen this pad yet, we need to
-                add a new label and jump to the correct section.  */
-             if (pad_map[idx] == NULL_RTX)
-               {
-                 pad_map[idx] = gen_label_rtx ();
-                 if (prev_bb == NULL)
-                   for (iter = section_switch_note;
-                        iter; iter = PREV_INSN (iter))
-                     if (NOTE_INSN_BASIC_BLOCK_P (iter))
-                       {
-                         prev_bb = NOTE_BASIC_BLOCK (iter);
-                         break;
-                       }
-                 if (cur_sec == 0)
-                   {
-                     note = emit_label_before (pad_map[idx],
-                                               section_switch_note);
-                     jump = emit_jump_insn_before (gen_jump (cs->landing_pad),
-                                                   section_switch_note);
-                   }
-                 else
-                   {
-                     jump = emit_jump_insn_after (gen_jump (cs->landing_pad),
-                                                  section_switch_note);
-                     note = emit_label_after (pad_map[idx],
-                                              section_switch_note);
-                   }
-                 JUMP_LABEL (jump) = cs->landing_pad;
-                 add_reg_note (jump, REG_CROSSING_JUMP, NULL_RTX);
-                 iter = NEXT_INSN (cs->landing_pad);
-                 if (iter && NOTE_INSN_BASIC_BLOCK_P (iter))
-                   padbb = NOTE_BASIC_BLOCK (iter);
-                 else
-                   padbb = NULL;
-                 if (padbb && prev_bb
-                     && BB_PARTITION (padbb) != BB_UNPARTITIONED)
-                   {
-                     basic_block bb;
-                     int part
-                       = BB_PARTITION (padbb) == BB_COLD_PARTITION
-                         ? BB_HOT_PARTITION : BB_COLD_PARTITION;
-                     edge_iterator ei;
-                     edge e;
-
-                     bb = create_basic_block (note, jump, prev_bb);
-                     make_single_succ_edge (bb, padbb, EDGE_CROSSING);
-                     BB_SET_PARTITION (bb, part);
-                     for (ei = ei_start (padbb->preds);
-                          (e = ei_safe_edge (ei)); )
-                       {
-                         if ((e->flags & (EDGE_EH|EDGE_CROSSING))
-                             == (EDGE_EH|EDGE_CROSSING))
-                           {
-                             redirect_edge_succ (e, bb);
-                             e->flags &= ~EDGE_CROSSING;
-                           }
-                         else
-                           ei_next (&ei);
-                       }
-                     if (cur_sec == 0)
-                       prev_bb = bb;
-                   }
-               }
-             cs->landing_pad = pad_map[idx];
-           }
-       }
-
-      sbitmap_free (pad_loc);
-      XDELETEVEC (pad_map);
-    }
-
   htab_delete (ar_hash);
   return 0;
 }
index 14eca870a70dcc4e3155d73e34ed54dabe7fb90f..5d461d7000b651e1016561a8f2e44ffeccf487f9 100644 (file)
@@ -253,6 +253,7 @@ extern rtx expand_builtin_dwarf_sp_column (void);
 extern void expand_builtin_eh_return (tree, tree);
 extern void expand_eh_return (void);
 extern rtx expand_builtin_extend_pointer (tree);
+extern void expand_dw2_landing_pad_for_region (eh_region);
 
 typedef tree (*duplicate_eh_regions_map) (tree, void *);
 extern struct pointer_map_t *duplicate_eh_regions
index bc71dd60fa138560b8c3142cf71a53d91e58ff67..120790819140512995864cd4e3d014856e28b2ae 100644 (file)
@@ -1421,7 +1421,7 @@ gimple_can_merge_blocks_p (basic_block a, basic_block b)
   if (!single_succ_p (a))
     return false;
 
-  if (single_succ_edge (a)->flags & (EDGE_ABNORMAL | EDGE_EH))
+  if (single_succ_edge (a)->flags & (EDGE_ABNORMAL | EDGE_EH | EDGE_PRESERVE))
     return false;
 
   if (single_succ (a) != b)