aboutsummaryrefslogtreecommitdiff
path: root/gcc/except.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2011-07-23 19:44:19 +0000
committerRichard Henderson <rth@redhat.com>2011-07-23 19:44:19 +0000
commit7ddda58dd792bb3ba147f99592f075f078f6de90 (patch)
tree389d88dc095866e7b7f73e8f1553aa55bd3617a1 /gcc/except.c
parent0a4e3e51a6a69885b1f8dcd6c5b1bf28502d25ff (diff)
bb-reorder: Split EH edges crossing partitions.
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@176696 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/except.c')
-rw-r--r--gcc/except.c166
1 files changed, 38 insertions, 128 deletions
diff --git a/gcc/except.c b/gcc/except.c
index bb16036d361..8d56e105fbe 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -919,6 +919,34 @@ emit_to_new_bb_before (rtx seq, rtx insn)
return bb;
}
+/* 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;
}