From 12c3874e62ea28f9df3f14e93bba5f624b1a15d9 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Wed, 25 Feb 2004 21:00:00 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 12 +++++ gcc/basic-block.h | 2 + gcc/cfgbuild.c | 3 +- gcc/cfglayout.c | 20 ++++---- gcc/except.c | 128 +++++++++++++++++++++++++++++++++++++++++----- 5 files changed, 140 insertions(+), 25 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7bac5394451..74073e2b369 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2004-02-25 Jan Hubicka + + * 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 * config.gcc (hppa*-*-*, parisc*-*-*): Add MASK_BIG_SWITCH to all diff --git a/gcc/basic-block.h b/gcc/basic-block.h index 3f1775d8c36..05f41c01948 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -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" diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c index 5805e587ec8..00c53a46ce8 100644 --- a/gcc/cfgbuild.c +++ b/gcc/cfgbuild.c @@ -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; diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c index 41d92bbee6c..25349658355 100644 --- a/gcc/cfglayout.c +++ b/gcc/cfglayout.c @@ -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) diff --git a/gcc/except.c b/gcc/except.c index 5d85e512358..70eb3b17d7f 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -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); } -- 2.30.2