basic-block.h (make_eh_edge, [...]): Declare.

* basic-block.h (make_eh_edge, break_superblocks): Declare.
	* cfgbuild.c (make_eh_edge):  Make global.
	* cfglayout.c (break_superblocks): Likewise; fix memory leak.
	* except.c (build_post_landing_pads, connect_post_landing_pads,
	dw2_build_landing_pads, sjlj_emit_function_enter,
	sjlj_emit_function_exit, sjlj_emit_dispatch_table,
	sjlj_build_landing_pads): Update CFG.
	(emit_to_new_bb_before): New function.
	(finish_eh_generation): Do not rebuild the CFG.

From-SVN: r78448
This commit is contained in:
Jan Hubicka 2004-02-25 21:00:00 +01:00 committed by Jan Hubicka
parent b29610b3cf
commit 12c3874e62
5 changed files with 140 additions and 25 deletions

View File

@ -1,3 +1,15 @@
2004-02-25 Jan Hubicka <jh@suse.cz>
* basic-block.h (make_eh_edge, break_superblocks): Declare.
* cfgbuild.c (make_eh_edge): Make global.
* cfglayout.c (break_superblocks): Likewise; fix memory leak.
* except.c (build_post_landing_pads, connect_post_landing_pads,
dw2_build_landing_pads, sjlj_emit_function_enter,
sjlj_emit_function_exit, sjlj_emit_dispatch_table,
sjlj_build_landing_pads): Update CFG.
(emit_to_new_bb_before): New function.
(finish_eh_generation): Do not rebuild the CFG.
2004-02-25 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
* config.gcc (hppa*-*-*, parisc*-*-*): Add MASK_BIG_SWITCH to all

View File

@ -566,6 +566,7 @@ extern bool purge_all_dead_edges (int);
extern bool purge_dead_edges (basic_block);
extern void find_sub_basic_blocks (basic_block);
extern void find_many_sub_basic_blocks (sbitmap);
extern void make_eh_edge (sbitmap *, basic_block, rtx);
extern bool can_fallthru (basic_block, basic_block);
extern void flow_nodes_print (const char *, const sbitmap, FILE *);
extern void flow_edge_list_print (const char *, const edge *, int, FILE *);
@ -649,6 +650,7 @@ extern void verify_dominators (enum cdi_direction);
extern basic_block first_dom_son (enum cdi_direction, basic_block);
extern basic_block next_dom_son (enum cdi_direction, basic_block);
extern bool try_redirect_by_replacing_jump (edge, basic_block, bool);
extern void break_superblocks (void);
#include "cfghooks.h"

View File

@ -53,7 +53,6 @@ static void find_basic_blocks_1 (rtx);
static rtx find_label_refs (rtx, rtx);
static void make_edges (rtx, basic_block, basic_block, int);
static void make_label_edge (sbitmap *, basic_block, rtx, int);
static void make_eh_edge (sbitmap *, basic_block, rtx);
static void find_bb_boundaries (basic_block);
static void compute_outgoing_frequencies (basic_block);
@ -240,7 +239,7 @@ make_label_edge (sbitmap *edge_cache, basic_block src, rtx label, int flags)
/* Create the edges generated by INSN in REGION. */
static void
void
make_eh_edge (sbitmap *edge_cache, basic_block src, rtx insn)
{
int is_call = GET_CODE (insn) == CALL_INSN ? EDGE_ABNORMAL_CALL : 0;

View File

@ -56,7 +56,6 @@ static void change_scope (rtx, tree, tree);
void verify_insn_chain (void);
static void fixup_fallthru_exit_predecessor (void);
static rtx duplicate_insn_chain (rtx, rtx);
static void break_superblocks (void);
static tree insn_scope (rtx);
rtx
@ -1144,23 +1143,22 @@ cfg_layout_initialize (void)
}
/* Splits superblocks. */
static void
void
break_superblocks (void)
{
sbitmap superblocks;
int i, need;
bool need = false;
basic_block bb;
superblocks = sbitmap_alloc (n_basic_blocks);
superblocks = sbitmap_alloc (last_basic_block);
sbitmap_zero (superblocks);
need = 0;
for (i = 0; i < n_basic_blocks; i++)
if (BASIC_BLOCK(i)->flags & BB_SUPERBLOCK)
FOR_EACH_BB (bb)
if (bb->flags & BB_SUPERBLOCK)
{
BASIC_BLOCK(i)->flags &= ~BB_SUPERBLOCK;
SET_BIT (superblocks, i);
need = 1;
bb->flags &= ~BB_SUPERBLOCK;
SET_BIT (superblocks, bb->index);
need = true;
}
if (need)

View File

@ -1629,6 +1629,24 @@ assign_filter_values (void)
htab_delete (ehspec);
}
/* Emit SEQ into basic block just before INSN (that is assumed to be
first instruction of some existing BB and return the newly
produced block. */
static basic_block
emit_to_new_bb_before (rtx seq, rtx insn)
{
rtx last;
basic_block bb;
last = emit_insn_before (seq, insn);
if (GET_CODE (last) == BARRIER)
last = PREV_INSN (last);
bb = create_basic_block (seq, last, BLOCK_FOR_INSN (insn)->prev_bb);
update_bb_for_insn (bb);
bb->flags |= BB_SUPERBLOCK;
return bb;
}
/* Generate the code to actually handle exceptions, which will follow the
landing pads. */
@ -1702,7 +1720,8 @@ build_post_landing_pads (void)
seq = get_insns ();
end_sequence ();
emit_insn_before (seq, region->u.try.catch->label);
emit_to_new_bb_before (seq, region->u.try.catch->label);
break;
case ERT_ALLOWED_EXCEPTIONS:
@ -1726,7 +1745,7 @@ build_post_landing_pads (void)
seq = get_insns ();
end_sequence ();
emit_insn_before (seq, region->label);
emit_to_new_bb_before (seq, region->label);
break;
case ERT_CLEANUP:
@ -1758,6 +1777,7 @@ connect_post_landing_pads (void)
struct eh_region *region = cfun->eh->region_array[i];
struct eh_region *outer;
rtx seq;
rtx barrier;
/* Mind we don't process a region more than once. */
if (!region || region->region_number != i)
@ -1776,14 +1796,30 @@ connect_post_landing_pads (void)
start_sequence ();
if (outer)
emit_jump (outer->post_landing_pad);
{
edge e;
basic_block src, dest;
emit_jump (outer->post_landing_pad);
src = BLOCK_FOR_INSN (region->resume);
dest = BLOCK_FOR_INSN (outer->post_landing_pad);
while (src->succ)
remove_edge (src->succ);
e = make_edge (src, dest, 0);
e->probability = REG_BR_PROB_BASE;
e->count = src->count;
}
else
emit_library_call (unwind_resume_libfunc, LCT_THROW,
VOIDmode, 1, cfun->eh->exc_ptr, ptr_mode);
seq = get_insns ();
end_sequence ();
emit_insn_before (seq, region->resume);
barrier = emit_insn_before (seq, region->resume);
/* Avoid duplicate barrier. */
if (GET_CODE (barrier) != BARRIER)
abort ();
delete_insn (barrier);
delete_insn (region->resume);
}
}
@ -1799,7 +1835,9 @@ dw2_build_landing_pads (void)
{
struct eh_region *region = cfun->eh->region_array[i];
rtx seq;
basic_block bb;
bool clobbers_hard_regs = false;
edge e;
/* Mind we don't process a region more than once. */
if (!region || region->region_number != i)
@ -1859,7 +1897,10 @@ dw2_build_landing_pads (void)
seq = get_insns ();
end_sequence ();
emit_insn_before (seq, region->post_landing_pad);
bb = emit_to_new_bb_before (seq, region->post_landing_pad);
e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
e->count = bb->count;
e->probability = REG_BR_PROB_BASE;
}
}
@ -2107,9 +2148,21 @@ sjlj_emit_function_enter (rtx dispatch_label)
for (fn_begin = get_insns (); ; fn_begin = NEXT_INSN (fn_begin))
if (GET_CODE (fn_begin) == NOTE
&& NOTE_LINE_NUMBER (fn_begin) == NOTE_INSN_FUNCTION_BEG)
&& (NOTE_LINE_NUMBER (fn_begin) == NOTE_INSN_FUNCTION_BEG
|| NOTE_LINE_NUMBER (fn_begin) == NOTE_INSN_BASIC_BLOCK))
break;
emit_insn_after (seq, fn_begin);
if (NOTE_LINE_NUMBER (fn_begin) == NOTE_INSN_FUNCTION_BEG)
insert_insn_on_edge (seq, ENTRY_BLOCK_PTR->succ);
else
{
rtx last = BB_END (ENTRY_BLOCK_PTR->succ->dest);
for (; ; fn_begin = NEXT_INSN (fn_begin))
if ((GET_CODE (fn_begin) == NOTE
&& NOTE_LINE_NUMBER (fn_begin) == NOTE_INSN_FUNCTION_BEG)
|| fn_begin == last)
break;
emit_insn_after (seq, fn_begin);
}
}
/* Call back from expand_function_end to know where we should put
@ -2125,6 +2178,7 @@ static void
sjlj_emit_function_exit (void)
{
rtx seq;
edge e;
start_sequence ();
@ -2138,7 +2192,31 @@ sjlj_emit_function_exit (void)
post-dominates all can_throw_internal instructions. This is
the last possible moment. */
emit_insn_after (seq, cfun->eh->sjlj_exit_after);
for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
if (e->flags & EDGE_FALLTHRU)
break;
if (e)
{
rtx insn;
/* Figure out whether the place we are supposed to insert libcall
is inside the last basic block or after it. In the other case
we need to emit to edge. */
if (e->src->next_bb != EXIT_BLOCK_PTR)
abort ();
for (insn = NEXT_INSN (BB_END (e->src)); insn; insn = NEXT_INSN (insn))
if (insn == cfun->eh->sjlj_exit_after)
break;
if (insn)
insert_insn_on_edge (seq, e);
else
{
insn = cfun->eh->sjlj_exit_after;
if (GET_CODE (insn) == CODE_LABEL)
insn = NEXT_INSN (insn);
emit_insn_after (seq, insn);
}
}
}
static void
@ -2146,6 +2224,9 @@ sjlj_emit_dispatch_table (rtx dispatch_label, struct sjlj_lp_info *lp_info)
{
int i, first_reachable;
rtx mem, dispatch, seq, fc;
rtx before;
basic_block bb;
edge e;
fc = cfun->eh->sjlj_fc;
@ -2200,8 +2281,12 @@ sjlj_emit_dispatch_table (rtx dispatch_label, struct sjlj_lp_info *lp_info)
seq = get_insns ();
end_sequence ();
emit_insn_before (seq, (cfun->eh->region_array[first_reachable]
->post_landing_pad));
before = cfun->eh->region_array[first_reachable]->post_landing_pad;
bb = emit_to_new_bb_before (seq, before);
e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
e->count = bb->count;
e->probability = REG_BR_PROB_BASE;
}
static void
@ -2235,6 +2320,8 @@ sjlj_build_landing_pads (void)
void
finish_eh_generation (void)
{
basic_block bb;
/* Nothing to do if no regions created. */
if (cfun->eh->region_tree == NULL)
return;
@ -2269,8 +2356,25 @@ finish_eh_generation (void)
/* We've totally changed the CFG. Start over. */
find_exception_handler_labels ();
rebuild_jump_labels (get_insns ());
find_basic_blocks (get_insns (), max_reg_num (), 0);
break_superblocks ();
if (USING_SJLJ_EXCEPTIONS)
commit_edge_insertions ();
FOR_EACH_BB (bb)
{
edge e, next;
bool eh = false;
for (e = bb->succ; e; e = next)
{
next = e->succ_next;
if (e->flags & EDGE_EH)
{
remove_edge (e);
eh = true;
}
}
if (eh)
make_eh_edge (NULL, bb, BB_END (bb));
}
cleanup_cfg (CLEANUP_PRE_LOOP | CLEANUP_NO_INSN_DEL);
}