re PR rtl-optimization/85638 (build failure for Ada runtime with SJLJ exceptions...
authorEric Botcazou <ebotcazou@adacore.com>
Wed, 9 May 2018 07:58:29 +0000 (07:58 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Wed, 9 May 2018 07:58:29 +0000 (07:58 +0000)
PR rtl-optimization/85638
* bb-reorder.c: Include common/common-target.h.
(create_forwarder_block): New function extracted from...
(fix_up_crossing_landing_pad): ...here.  Rename into...
(dw2_fix_up_crossing_landing_pad): ...this.
(sjlj_fix_up_crossing_landing_pad): New function.
(find_rarely_executed_basic_blocks_and_crossing_edges): In SJLJ mode,
call sjlj_fix_up_crossing_landing_pad if there are incoming EH edges
from both partitions and exit the loop after one iteration.

From-SVN: r260070

gcc/ChangeLog
gcc/bb-reorder.c

index 89ad01b872981b630f2a2a716327d1f5d090f14c..7a36aeb65a441c8eaeb37e4ed4c08c4cbb1fd32b 100644 (file)
@@ -1,3 +1,15 @@
+2018-05-09  Eric Botcazou  <ebotcazou@adacore.com>
+
+       PR rtl-optimization/85638
+       * bb-reorder.c: Include common/common-target.h.
+       (create_forwarder_block): New function extracted from...
+       (fix_up_crossing_landing_pad): ...here.  Rename into...
+       (dw2_fix_up_crossing_landing_pad): ...this.
+       (sjlj_fix_up_crossing_landing_pad): New function.
+       (find_rarely_executed_basic_blocks_and_crossing_edges): In SJLJ mode,
+       call sjlj_fix_up_crossing_landing_pad if there are incoming EH edges
+       from both partitions and exit the loop after one iteration.
+
 2018-05-08  Kelvin Nilsen  <kelvin@gcc.gnu.org>
 
        Revert:
index bc08e11a81dc19f42eea12ebc008a72fddf907ca..6f2ad5a522058333015ee24aa96d50d86856d70b 100644 (file)
 #include "fibonacci_heap.h"
 #include "stringpool.h"
 #include "attribs.h"
+#include "common/common-target.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
@@ -1408,17 +1409,95 @@ get_uncond_jump_length (void)
   return length;
 }
 
+/* Create a forwarder block to OLD_BB starting with NEW_LABEL and in the
+   other partition wrt OLD_BB.  */
+
+static basic_block
+create_forwarder_block (rtx_code_label *new_label, basic_block old_bb)
+{
+  /* Put the new label and a jump in the new basic block.  */
+  rtx_insn *label = emit_label (new_label);
+  rtx_code_label *old_label = block_label (old_bb);
+  rtx_insn *jump = emit_jump_insn (targetm.gen_jump (old_label));
+  JUMP_LABEL (jump) = old_label;
+
+  /* Create the new basic block and put it in last position.  */
+  basic_block last_bb = EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb;
+  basic_block new_bb = create_basic_block (label, jump, last_bb);
+  new_bb->aux = last_bb->aux;
+  new_bb->count = old_bb->count;
+  last_bb->aux = new_bb;
+
+  emit_barrier_after_bb (new_bb);
+
+  make_single_succ_edge (new_bb, old_bb, 0);
+
+  /* Make sure the new basic block is in the other partition.  */
+  unsigned new_partition = BB_PARTITION (old_bb);
+  new_partition ^= BB_HOT_PARTITION | BB_COLD_PARTITION;
+  BB_SET_PARTITION (new_bb, new_partition);
+
+  return new_bb;
+}
+
+/* The common landing pad in block OLD_BB has edges from both partitions.
+   Add a new landing pad that will just jump to the old one and split the
+   edges so that no EH edge crosses partitions.  */
+
+static void
+sjlj_fix_up_crossing_landing_pad (basic_block old_bb)
+{
+  const unsigned lp_len = cfun->eh->lp_array->length ();
+  edge_iterator ei;
+  edge e;
+
+  /* Generate the new common landing-pad label.  */
+  rtx_code_label *new_label = gen_label_rtx ();
+  LABEL_PRESERVE_P (new_label) = 1;
+
+  /* Create the forwarder block.  */
+  basic_block new_bb = create_forwarder_block (new_label, old_bb);
+
+  /* Create the map from old to new lp index and initialize it.  */
+  unsigned *index_map = (unsigned *) alloca (lp_len * sizeof (unsigned));
+  memset (index_map, 0, lp_len * sizeof (unsigned));
+
+  /* Fix up the edges.  */
+  for (ei = ei_start (old_bb->preds); (e = ei_safe_edge (ei)) != NULL; )
+    if (e->src != new_bb && BB_PARTITION (e->src) == BB_PARTITION (new_bb))
+      {
+       rtx_insn *insn = BB_END (e->src);
+       rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+
+       gcc_assert (note != NULL);
+       const unsigned old_index = INTVAL (XEXP (note, 0));
+
+       /* Generate the new landing-pad structure.  */
+       if (index_map[old_index] == 0)
+         {
+           eh_landing_pad old_lp = (*cfun->eh->lp_array)[old_index];
+           eh_landing_pad new_lp = gen_eh_landing_pad (old_lp->region);
+           new_lp->post_landing_pad = old_lp->post_landing_pad;
+           new_lp->landing_pad = new_label;
+           index_map[old_index] = new_lp->index;
+         }
+       XEXP (note, 0) = GEN_INT (index_map[old_index]);
+
+       /* Adjust the edge to the new destination.  */
+       redirect_edge_succ (e, new_bb);
+      }
+    else
+      ei_next (&ei);
+}
+
 /* The landing pad OLD_LP, in block OLD_BB, has edges from both partitions.
    Add a new landing pad that will just jump to the old one 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)
+dw2_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;
-  rtx_insn *jump;
-  unsigned new_partition;
   edge_iterator ei;
   edge e;
 
@@ -1428,32 +1507,12 @@ fix_up_crossing_landing_pad (eh_landing_pad old_lp, basic_block old_bb)
   new_lp->landing_pad = gen_label_rtx ();
   LABEL_PRESERVE_P (new_lp->landing_pad) = 1;
 
-  /* Put appropriate instructions in new bb.  */
-  rtx_code_label *new_label = emit_label (new_lp->landing_pad);
-
-  rtx_code_label *old_label = block_label (old_bb);
-  jump = emit_jump_insn (targetm.gen_jump (old_label));
-  JUMP_LABEL (jump) = old_label;
-
-  /* Create new basic block to be dest for lp.  */
-  last_bb = EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb;
-  new_bb = create_basic_block (new_label, jump, last_bb);
-  new_bb->aux = last_bb->aux;
-  new_bb->count = old_bb->count;
-  last_bb->aux = new_bb;
-
-  emit_barrier_after_bb (new_bb);
-
-  make_single_succ_edge (new_bb, old_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);
+  /* Create the forwarder block.  */
+  basic_block new_bb = create_forwarder_block (new_lp->landing_pad, old_bb);
 
   /* Fix up the edges.  */
   for (ei = ei_start (old_bb->preds); (e = ei_safe_edge (ei)) != NULL; )
-    if (e->src != new_bb && BB_PARTITION (e->src) == new_partition)
+    if (e->src != new_bb && BB_PARTITION (e->src) == BB_PARTITION (new_bb))
       {
        rtx_insn *insn = BB_END (e->src);
        rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
@@ -1652,9 +1711,11 @@ find_rarely_executed_basic_blocks_and_crossing_edges (void)
 
   /* 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.  */
+     moving the landing pads or inserting forwarder landing pads.  */
   if (cfun->eh->lp_array)
     {
+      const bool sjlj
+       = (targetm_common.except_unwind_info (&global_options) == UI_SJLJ);
       unsigned i;
       eh_landing_pad lp;
 
@@ -1686,13 +1747,18 @@ find_rarely_executed_basic_blocks_and_crossing_edges (void)
              which ^= BB_HOT_PARTITION | BB_COLD_PARTITION;
              BB_SET_PARTITION (bb, which);
            }
+         else if (sjlj)
+           sjlj_fix_up_crossing_landing_pad (bb);
          else
-           fix_up_crossing_landing_pad (lp, bb);
+           dw2_fix_up_crossing_landing_pad (lp, bb);
+
+         /* There is a single, common landing pad in SJLJ mode.  */
+         if (sjlj)
+           break;
        }
     }
 
   /* Mark every edge that crosses between sections.  */
-
   FOR_EACH_BB_FN (bb, cfun)
     FOR_EACH_EDGE (e, ei, bb->succs)
       {