X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcfgrtl.c;h=0edad6a1af316888b4122f883c50a8fcbc853233;hb=3cfd65257d3921ace74869698e8f856f5af9ff56;hp=e39b196be07ca520f933ec98177d0cf4f0591b94;hpb=7b07eae7ae7f573505fbcf944631f36ac6c8bf36;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index e39b196be07..0edad6a1af3 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -64,8 +64,6 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA static int can_delete_note_p (rtx); static int can_delete_label_p (rtx); static void commit_one_edge_insertion (edge, int); -static rtx last_loop_beg_note (rtx); -static bool back_edge_of_syntactic_loop_p (basic_block, basic_block); static basic_block rtl_split_edge (edge); static bool rtl_move_block_after (basic_block, basic_block); static int rtl_verify_flow_info (void); @@ -79,7 +77,6 @@ static edge rtl_redirect_edge_and_branch (edge, basic_block); static basic_block rtl_split_block (basic_block, void *); static void rtl_dump_bb (basic_block, FILE *, int); static int rtl_verify_flow_info_1 (void); -static void mark_killed_regs (rtx, rtx, void *); static void rtl_make_forwarder_block (edge); /* Return true if NOTE is not one of the ones that must be kept paired, @@ -115,8 +112,8 @@ delete_insn (rtx insn) if (LABEL_P (insn)) { /* Some labels can't be directly removed from the INSN chain, as they - might be references via variables, constant pool etc. - Convert them to the special NOTE_INSN_DELETED_LABEL note. */ + might be references via variables, constant pool etc. + Convert them to the special NOTE_INSN_DELETED_LABEL note. */ if (! can_delete_label_p (insn)) { const char *name = LABEL_NAME (insn); @@ -305,7 +302,7 @@ create_basic_block_structure (rtx head, rtx end, rtx bb_note, basic_block after) bb->index = last_basic_block++; bb->flags = BB_NEW | BB_RTL; link_block (bb, after); - BASIC_BLOCK (bb->index) = bb; + SET_BASIC_BLOCK (bb->index, bb); update_bb_for_insn (bb); BB_SET_PARTITION (bb, BB_UNPARTITIONED); @@ -328,10 +325,14 @@ rtl_create_basic_block (void *headp, void *endp, basic_block after) basic_block bb; /* Grow the basic block array if needed. */ - if ((size_t) last_basic_block >= VARRAY_SIZE (basic_block_info)) + if ((size_t) last_basic_block >= VEC_length (basic_block, basic_block_info)) { + size_t old_size = VEC_length (basic_block, basic_block_info); size_t new_size = last_basic_block + (last_basic_block + 3) / 4; - VARRAY_GROW (basic_block_info, new_size); + basic_block *p; + VEC_safe_grow (basic_block, gc, basic_block_info, new_size); + p = VEC_address (basic_block, basic_block_info); + memset (&p[old_size], 0, sizeof (basic_block) * (new_size - old_size)); } n_basic_blocks++; @@ -385,6 +386,13 @@ rtl_delete_block (basic_block b) /* Selectively delete the entire chain. */ BB_HEAD (b) = NULL; delete_insn_chain (insn, end); + if (b->il.rtl->global_live_at_start) + { + FREE_REG_SET (b->il.rtl->global_live_at_start); + FREE_REG_SET (b->il.rtl->global_live_at_end); + b->il.rtl->global_live_at_start = NULL; + b->il.rtl->global_live_at_end = NULL; + } } /* Records the basic block struct in BLOCK_FOR_INSN for every insn. */ @@ -410,13 +418,14 @@ compute_bb_for_insn (void) /* Release the basic_block_for_insn array. */ -void +unsigned int free_bb_for_insn (void) { rtx insn; for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) if (!BARRIER_P (insn)) BLOCK_FOR_INSN (insn) = NULL; + return 0; } struct tree_opt_pass pass_free_cfg = @@ -440,7 +449,21 @@ struct tree_opt_pass pass_free_cfg = rtx entry_of_function (void) { - return (n_basic_blocks ? BB_HEAD (ENTRY_BLOCK_PTR->next_bb) : get_insns ()); + return (n_basic_blocks > NUM_FIXED_BLOCKS ? + BB_HEAD (ENTRY_BLOCK_PTR->next_bb) : get_insns ()); +} + +/* Emit INSN at the entry point of the function, ensuring that it is only + executed once per function. */ +void +emit_insn_at_entry (rtx insn) +{ + edge_iterator ei = ei_start (ENTRY_BLOCK_PTR->succs); + edge e = ei_safe_edge (ei); + gcc_assert (e->flags & EDGE_FALLTHRU); + + insert_insn_on_edge (insn, e); + commit_edge_insertions (); } /* Update insns block within BB. */ @@ -542,7 +565,7 @@ rtl_merge_blocks (basic_block a, basic_block b) /* This might have been an EH label that no longer has incoming EH edges. Update data structures to match. */ maybe_remove_eh_handler (b_head); - + /* Detect basic blocks with nothing but a label. This can happen in particular at the end of a function. */ if (b_head == b_end) @@ -628,9 +651,9 @@ rtl_can_merge_blocks (basic_block a,basic_block b) and cold sections. Basic block partitioning may result in some jumps that appear to - be optimizable (or blocks that appear to be mergeable), but which really - must be left untouched (they are required to make it safely across - partition boundaries). See the comments at the top of + be optimizable (or blocks that appear to be mergeable), but which really + must be left untouched (they are required to make it safely across + partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ if (BB_PARTITION (a) != BB_PARTITION (b)) @@ -687,11 +710,11 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout) and cold sections. Basic block partitioning may result in some jumps that appear to - be optimizable (or blocks that appear to be mergeable), but which really - must be left untouched (they are required to make it safely across - partition boundaries). See the comments at the top of + be optimizable (or blocks that appear to be mergeable), but which really + must be left untouched (they are required to make it safely across + partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ - + if (find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX) || BB_PARTITION (src) != BB_PARTITION (target)) return NULL; @@ -736,7 +759,7 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout) { rtx insn = src->il.rtl->footer; - delete_insn_chain (kill_from, BB_END (src)); + delete_insn_chain (kill_from, BB_END (src)); /* Remove barriers but keep jumptables. */ while (insn) @@ -756,7 +779,7 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout) } } else - delete_insn_chain (kill_from, PREV_INSN (BB_HEAD (target))); + delete_insn_chain (kill_from, PREV_INSN (BB_HEAD (target))); } /* If this already is simplejump, redirect it. */ @@ -843,40 +866,12 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout) e->probability = REG_BR_PROB_BASE; e->count = src->count; - /* We don't want a block to end on a line-number note since that has - the potential of changing the code between -g and not -g. */ - while (NOTE_P (BB_END (e->src)) - && NOTE_LINE_NUMBER (BB_END (e->src)) >= 0) - delete_insn (BB_END (e->src)); - if (e->dest != target) redirect_edge_succ (e, target); return e; } -/* Return last loop_beg note appearing after INSN, before start of next - basic block. Return INSN if there are no such notes. - - When emitting jump to redirect a fallthru edge, it should always appear - after the LOOP_BEG notes, as loop optimizer expect loop to either start by - fallthru edge or jump following the LOOP_BEG note jumping to the loop exit - test. */ - -static rtx -last_loop_beg_note (rtx insn) -{ - rtx last = insn; - - for (insn = NEXT_INSN (insn); insn && NOTE_P (insn) - && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK; - insn = NEXT_INSN (insn)) - if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG) - last = insn; - - return last; -} - /* Redirect edge representing branch of (un)conditional jump or tablejump, NULL on failure */ static edge @@ -1013,9 +1008,6 @@ force_nonfallthru_and_redirect (edge e, basic_block target) by creating a basic block afterwards to redirect fallthru edge. */ if (e->src != ENTRY_BLOCK_PTR && e->dest != EXIT_BLOCK_PTR && any_condjump_p (BB_END (e->src)) - /* When called from cfglayout, fallthru edges do not - necessarily go to the next block. */ - && e->src->next_bb == e->dest && JUMP_LABEL (BB_END (e->src)) == BB_HEAD (e->dest)) { rtx note; @@ -1024,7 +1016,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target) redirected = redirect_jump (BB_END (e->src), block_label (target), 0); gcc_assert (redirected); - + note = find_reg_note (BB_END (e->src), REG_BR_PROB, NULL_RTX); if (note) { @@ -1063,9 +1055,9 @@ force_nonfallthru_and_redirect (edge e, basic_block target) edge tmp; edge_iterator ei; bool found = false; - + basic_block bb = create_basic_block (BB_HEAD (e->dest), NULL, ENTRY_BLOCK_PTR); - + /* Change the existing edge's source to be the new block, and add a new edge from the entry block to the new block. */ e->src = bb; @@ -1080,9 +1072,9 @@ force_nonfallthru_and_redirect (edge e, basic_block target) else ei_next (&ei); } - + gcc_assert (found); - + VEC_safe_push (edge, gc, bb->succs, e); make_single_succ_edge (ENTRY_BLOCK_PTR, bb, EDGE_FALLTHRU); } @@ -1097,9 +1089,6 @@ force_nonfallthru_and_redirect (edge e, basic_block target) forward from the last instruction of the old block. */ if (!tablejump_p (BB_END (e->src), NULL, ¬e)) note = BB_END (e->src); - - /* Position the new block correctly relative to loop notes. */ - note = last_loop_beg_note (note); note = NEXT_INSN (note); jump_block = create_basic_block (note, NULL, e->src); @@ -1129,8 +1118,8 @@ force_nonfallthru_and_redirect (edge e, basic_block target) NULL_RTX, REG_NOTES (BB_END - (jump_block))); - + (jump_block))); + /* Wire edge in. */ new_edge = make_edge (e->src, jump_block, EDGE_FALLTHRU); new_edge->probability = e->probability; @@ -1194,6 +1183,7 @@ rtl_redirect_edge_and_branch_force (edge e, basic_block target) /* In case the edge redirection failed, try to force it to be non-fallthru and redirect newly created simplejump. */ + e->src->flags |= BB_DIRTY; return force_nonfallthru_and_redirect (e, target); } @@ -1237,11 +1227,6 @@ rtl_tidy_fallthru_edge (edge e) #endif q = PREV_INSN (q); - - /* We don't want a block to end on a line-number note since that has - the potential of changing the code between -g and not -g. */ - while (NOTE_P (q) && NOTE_LINE_NUMBER (q) >= 0) - q = PREV_INSN (q); } /* Selectively unlink the sequence. */ @@ -1251,40 +1236,6 @@ rtl_tidy_fallthru_edge (edge e) e->flags |= EDGE_FALLTHRU; } -/* Helper function for split_edge. Return true in case edge BB2 to BB1 - is back edge of syntactic loop. */ - -static bool -back_edge_of_syntactic_loop_p (basic_block bb1, basic_block bb2) -{ - rtx insn; - int count = 0; - basic_block bb; - - if (bb1 == bb2) - return true; - - /* ??? Could we guarantee that bb indices are monotone, so that we could - just compare them? */ - for (bb = bb1; bb && bb != bb2; bb = bb->next_bb) - continue; - - if (!bb) - return false; - - for (insn = BB_END (bb1); insn != BB_HEAD (bb2) && count >= 0; - insn = NEXT_INSN (insn)) - if (NOTE_P (insn)) - { - if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG) - count++; - else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) - count--; - } - - return count >= 0; -} - /* Should move basic block BB after basic block AFTER. NIY. */ static bool @@ -1325,32 +1276,8 @@ rtl_split_edge (edge edge_in) force_nonfallthru (e); } - /* Create the basic block note. - - Where we place the note can have a noticeable impact on the generated - code. Consider this cfg: - - E - | - 0 - / \ - +->1-->2--->E - | | - +--+ - - If we need to insert an insn on the edge from block 0 to block 1, - we want to ensure the instructions we insert are outside of any - loop notes that physically sit between block 0 and block 1. Otherwise - we confuse the loop optimizer into thinking the loop is a phony. */ - - if (edge_in->dest != EXIT_BLOCK_PTR - && PREV_INSN (BB_HEAD (edge_in->dest)) - && NOTE_P (PREV_INSN (BB_HEAD (edge_in->dest))) - && (NOTE_LINE_NUMBER (PREV_INSN (BB_HEAD (edge_in->dest))) - == NOTE_INSN_LOOP_BEG) - && !back_edge_of_syntactic_loop_p (edge_in->dest, edge_in->src)) - before = PREV_INSN (BB_HEAD (edge_in->dest)); - else if (edge_in->dest != EXIT_BLOCK_PTR) + /* Create the basic block note. */ + if (edge_in->dest != EXIT_BLOCK_PTR) before = BB_HEAD (edge_in->dest); else before = NULL_RTX; @@ -1360,10 +1287,6 @@ rtl_split_edge (edge edge_in) if (edge_in->flags & EDGE_FALLTHRU && edge_in->dest == EXIT_BLOCK_PTR) { before = NEXT_INSN (BB_END (edge_in->src)); - if (before - && NOTE_P (before) - && NOTE_LINE_NUMBER (before) == NOTE_INSN_LOOP_END) - before = NEXT_INSN (before); bb = create_basic_block (before, NULL, edge_in->src); BB_COPY_PARTITION (bb, edge_in->src); } @@ -1422,114 +1345,6 @@ insert_insn_on_edge (rtx pattern, edge e) end_sequence (); } -/* Called from safe_insert_insn_on_edge through note_stores, marks live - registers that are killed by the store. */ -static void -mark_killed_regs (rtx reg, rtx set ATTRIBUTE_UNUSED, void *data) -{ - regset killed = data; - int regno, i; - - if (GET_CODE (reg) == SUBREG) - reg = SUBREG_REG (reg); - if (!REG_P (reg)) - return; - regno = REGNO (reg); - if (regno >= FIRST_PSEUDO_REGISTER) - SET_REGNO_REG_SET (killed, regno); - else - { - for (i = 0; i < (int) hard_regno_nregs[regno][GET_MODE (reg)]; i++) - SET_REGNO_REG_SET (killed, regno + i); - } -} - -/* Similar to insert_insn_on_edge, tries to put INSN to edge E. Additionally - it checks whether this will not clobber the registers that are live on the - edge (i.e. it requires liveness information to be up-to-date) and if there - are some, then it tries to save and restore them. Returns true if - successful. */ -bool -safe_insert_insn_on_edge (rtx insn, edge e) -{ - rtx x; - regset killed; - rtx save_regs = NULL_RTX; - unsigned regno; - int noccmode; - enum machine_mode mode; - reg_set_iterator rsi; - -#ifdef AVOID_CCMODE_COPIES - noccmode = true; -#else - noccmode = false; -#endif - - killed = ALLOC_REG_SET (®_obstack); - - for (x = insn; x; x = NEXT_INSN (x)) - if (INSN_P (x)) - note_stores (PATTERN (x), mark_killed_regs, killed); - - /* Mark all hard registers as killed. Register allocator/reload cannot - cope with the situation when life range of hard register spans operation - for that the appropriate register is needed, i.e. it would be unsafe to - extend the life ranges of hard registers. */ - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - if (!fixed_regs[regno] - && !REGNO_PTR_FRAME_P (regno)) - SET_REGNO_REG_SET (killed, regno); - - bitmap_and_into (killed, e->dest->il.rtl->global_live_at_start); - - EXECUTE_IF_SET_IN_REG_SET (killed, 0, regno, rsi) - { - mode = regno < FIRST_PSEUDO_REGISTER - ? reg_raw_mode[regno] - : GET_MODE (regno_reg_rtx[regno]); - if (mode == VOIDmode) - return false; - - if (noccmode && mode == CCmode) - return false; - - save_regs = alloc_EXPR_LIST (0, - alloc_EXPR_LIST (0, - gen_reg_rtx (mode), - gen_raw_REG (mode, regno)), - save_regs); - } - - if (save_regs) - { - rtx from, to; - - start_sequence (); - for (x = save_regs; x; x = XEXP (x, 1)) - { - from = XEXP (XEXP (x, 0), 1); - to = XEXP (XEXP (x, 0), 0); - emit_move_insn (to, from); - } - emit_insn (insn); - for (x = save_regs; x; x = XEXP (x, 1)) - { - from = XEXP (XEXP (x, 0), 0); - to = XEXP (XEXP (x, 0), 1); - emit_move_insn (to, from); - } - insn = get_insns (); - end_sequence (); - free_EXPR_LIST_list (&save_regs); - } - insert_insn_on_edge (insn, e); - - FREE_REG_SET (killed); - - return true; -} - /* Update the CFG for the instructions queued on edge E. */ static void @@ -1564,7 +1379,7 @@ commit_one_edge_insertion (edge e, int watch_calls) if (!before && !after) { /* Figure out where to put these things. If the destination has - one predecessor, insert there. Except for the exit block. */ + one predecessor, insert there. Except for the exit block. */ if (single_pred_p (e->dest) && e->dest != EXIT_BLOCK_PTR) { bb = e->dest; @@ -1585,7 +1400,7 @@ commit_one_edge_insertion (edge e, int watch_calls) } /* If the source has one successor and the edge is not abnormal, - insert there. Except for the entry block. */ + insert there. Except for the entry block. */ else if ((e->flags & EDGE_ABNORMAL) == 0 && single_succ_p (e->src) && e->src != ENTRY_BLOCK_PTR) @@ -1599,11 +1414,7 @@ commit_one_edge_insertion (edge e, int watch_calls) We know this block has a single successor, so we can just emit the queued insns before the jump. */ if (JUMP_P (BB_END (bb))) - for (before = BB_END (bb); - NOTE_P (PREV_INSN (before)) - && NOTE_LINE_NUMBER (PREV_INSN (before)) == - NOTE_INSN_LOOP_BEG; before = PREV_INSN (before)) - ; + before = BB_END (bb); else { /* We'd better be fallthru, or we've lost track of @@ -1639,8 +1450,8 @@ commit_one_edge_insertion (edge e, int watch_calls) if (JUMP_P (BB_END (bb)) && !any_condjump_p (BB_END (bb)) - && (single_succ_edge (bb)->flags & EDGE_CROSSING)) - REG_NOTES (BB_END (bb)) = gen_rtx_EXPR_LIST + && (single_succ_edge (bb)->flags & EDGE_CROSSING)) + REG_NOTES (BB_END (bb)) = gen_rtx_EXPR_LIST (REG_CROSSING_JUMP, NULL_RTX, REG_NOTES (BB_END (bb))); } } @@ -1659,9 +1470,9 @@ commit_one_edge_insertion (edge e, int watch_calls) if (returnjump_p (last)) { /* ??? Remove all outgoing edges from BB and add one for EXIT. - This is not currently a problem because this only happens - for the (single) epilogue, which already has a fallthru edge - to EXIT. */ + This is not currently a problem because this only happens + for the (single) epilogue, which already has a fallthru edge + to EXIT. */ e = single_succ_edge (bb); gcc_assert (e->dest == EXIT_BLOCK_PTR @@ -1714,7 +1525,7 @@ commit_edge_insertions (void) FOR_EACH_BB (bb) if (bb->aux) { - SET_BIT (blocks, bb->index); + SET_BIT (blocks, bb->index); /* Check for forgotten bb->aux values before commit_edge_insertions call. */ gcc_assert (bb->aux == &bb->aux); @@ -1759,7 +1570,7 @@ commit_edge_insertions_watch_calls (void) FOR_EACH_BB (bb) if (bb->aux) { - SET_BIT (blocks, bb->index); + SET_BIT (blocks, bb->index); /* Check for forgotten bb->aux values before commit_edge_insertions call. */ gcc_assert (bb->aux == &bb->aux); @@ -1810,9 +1621,9 @@ print_rtl_with_bb (FILE *outf, rtx rtx_first) { enum bb_state { NOT_IN_BB, IN_ONE_BB, IN_MULTIPLE_BB }; int max_uid = get_max_uid (); - basic_block *start = xcalloc (max_uid, sizeof (basic_block)); - basic_block *end = xcalloc (max_uid, sizeof (basic_block)); - enum bb_state *in_bb_p = xcalloc (max_uid, sizeof (enum bb_state)); + basic_block *start = XCNEWVEC (basic_block, max_uid); + basic_block *end = XCNEWVEC (basic_block, max_uid); + enum bb_state *in_bb_p = XCNEWVEC (enum bb_state, max_uid); basic_block bb; @@ -1920,7 +1731,7 @@ rtl_verify_flow_info_1 (void) int err = 0; basic_block bb; - bb_info = xcalloc (max_uid, sizeof (basic_block)); + bb_info = XCNEWVEC (basic_block, max_uid); FOR_EACH_BB_REVERSE (bb) { @@ -2004,7 +1815,7 @@ rtl_verify_flow_info_1 (void) || (BB_PARTITION (e->src) != BB_PARTITION (e->dest) && e->src != ENTRY_BLOCK_PTR && e->dest != EXIT_BLOCK_PTR)) - { + { error ("fallthru edge crosses section boundary (bb %i)", e->src->index); err = 1; @@ -2052,9 +1863,10 @@ rtl_verify_flow_info_1 (void) err = 1; } if (n_branch != 1 && any_condjump_p (BB_END (bb)) - && JUMP_LABEL (BB_END (bb)) == BB_HEAD (fallthru->dest)) + && JUMP_LABEL (BB_END (bb)) != BB_HEAD (fallthru->dest)) { - error ("wrong amount of branch edges after conditional jump %i", bb->index); + error ("wrong amount of branch edges after conditional jump %i", + bb->index); err = 1; } if (n_call && !CALL_P (BB_END (bb))) @@ -2091,7 +1903,7 @@ rtl_verify_flow_info_1 (void) } /* OK pointers are correct. Now check the header of basic - block. It ought to contain optional CODE_LABEL followed + block. It ought to contain optional CODE_LABEL followed by NOTE_BASIC_BLOCK. */ x = BB_HEAD (bb); if (LABEL_P (x)) @@ -2193,7 +2005,7 @@ rtl_verify_flow_info (void) } else if (e->src != ENTRY_BLOCK_PTR && e->dest != EXIT_BLOCK_PTR) - { + { rtx insn; if (e->src->next_bb != e->dest) @@ -2213,7 +2025,7 @@ rtl_verify_flow_info (void) fatal_insn ("wrong insn in the fallthru edge", insn); err = 1; } - } + } } num_bb_notes = 0; @@ -2264,7 +2076,7 @@ rtl_verify_flow_info (void) curr_bb = NULL; } - if (num_bb_notes != n_basic_blocks) + if (num_bb_notes != n_basic_blocks - NUM_FIXED_BLOCKS) internal_error ("number of bb notes in insn chain (%d) != n_basic_blocks (%d)", num_bb_notes, n_basic_blocks); @@ -2300,9 +2112,15 @@ purge_dead_edges (basic_block bb) /* Cleanup abnormal edges caused by exceptions or non-local gotos. */ for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); ) { + /* There are three types of edges we need to handle correctly here: EH + edges, abnormal call EH edges, and abnormal call non-EH edges. The + latter can appear when nonlocal gotos are used. */ if (e->flags & EDGE_EH) { - if (can_throw_internal (BB_END (bb))) + if (can_throw_internal (BB_END (bb)) + /* If this is a call edge, verify that this is a call insn. */ + && (! (e->flags & EDGE_ABNORMAL_CALL) + || CALL_P (BB_END (bb)))) { ei_next (&ei); continue; @@ -2562,7 +2380,7 @@ cfg_layout_redirect_edge_and_branch (edge e, basic_block dest) BB_END (src))) { edge redirected; - + if (dump_file) fprintf (dump_file, "Fallthru edge unified with branch " "%i->%i redirected to %i\n", @@ -2571,11 +2389,11 @@ cfg_layout_redirect_edge_and_branch (edge e, basic_block dest) redirected = redirect_branch_edge (e, dest); gcc_assert (redirected); e->flags |= EDGE_FALLTHRU; - e->src->flags |= BB_DIRTY; + e->src->flags |= BB_DIRTY; return e; } /* In case we are redirecting fallthru edge to the branch edge - of conditional jump, remove it. */ + of conditional jump, remove it. */ if (EDGE_COUNT (src->succs) == 2) { /* Find the edge that is different from E. */ @@ -2703,9 +2521,9 @@ cfg_layout_can_merge_blocks_p (basic_block a, basic_block b) and cold sections. Basic block partitioning may result in some jumps that appear to - be optimizable (or blocks that appear to be mergeable), but which really - must be left untouched (they are required to make it safely across - partition boundaries). See the comments at the top of + be optimizable (or blocks that appear to be mergeable), but which really + must be left untouched (they are required to make it safely across + partition boundaries). See the comments at the top of bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ if (BB_PARTITION (a) != BB_PARTITION (b)) @@ -2741,7 +2559,7 @@ cfg_layout_merge_blocks (basic_block a, basic_block b) /* This might have been an EH label that no longer has incoming EH edges. Update data structures to match. */ maybe_remove_eh_handler (BB_HEAD (b)); - + delete_insn (BB_HEAD (b)); } @@ -2913,7 +2731,7 @@ rtl_flow_call_edges_add (sbitmap blocks) int last_bb = last_basic_block; bool check_last_block = false; - if (n_basic_blocks == 0) + if (n_basic_blocks == NUM_FIXED_BLOCKS) return 0; if (! blocks) @@ -2960,7 +2778,7 @@ rtl_flow_call_edges_add (sbitmap blocks) calls since there is no way that we can determine if they will return or not... */ - for (i = 0; i < last_bb; i++) + for (i = NUM_FIXED_BLOCKS; i < last_bb; i++) { basic_block bb = BASIC_BLOCK (i); rtx insn; @@ -2981,14 +2799,14 @@ rtl_flow_call_edges_add (sbitmap blocks) rtx split_at_insn = insn; /* Don't split the block between a call and an insn that should - remain in the same block as the call. */ + remain in the same block as the call. */ if (CALL_P (insn)) while (split_at_insn != BB_END (bb) && keep_with_call_p (NEXT_INSN (split_at_insn))) split_at_insn = NEXT_INSN (split_at_insn); /* The handling above of the final block before the epilogue - should be enough to verify that there is no edge to the exit + should be enough to verify that there is no edge to the exit block in CFG already. Calling make_edge in such case would cause us to mark that edge as fake and remove it later. */ @@ -3030,8 +2848,8 @@ rtl_flow_call_edges_add (sbitmap blocks) in trees, and this should be of the same type since it is a hook. */ static void rtl_lv_add_condition_to_bb (basic_block first_head , - basic_block second_head ATTRIBUTE_UNUSED, - basic_block cond_bb, void *comp_rtx) + basic_block second_head ATTRIBUTE_UNUSED, + basic_block cond_bb, void *comp_rtx) { rtx label, seq, jump; rtx op0 = XEXP ((rtx)comp_rtx, 0); @@ -3090,6 +2908,93 @@ init_rtl_bb_info (basic_block bb) } +/* Add EXPR to the end of basic block BB. */ + +rtx +insert_insn_end_bb_new (rtx pat, basic_block bb) +{ + rtx insn = BB_END (bb); + rtx new_insn; + rtx pat_end = pat; + + while (NEXT_INSN (pat_end) != NULL_RTX) + pat_end = NEXT_INSN (pat_end); + + /* If the last insn is a jump, insert EXPR in front [taking care to + handle cc0, etc. properly]. Similarly we need to care trapping + instructions in presence of non-call exceptions. */ + + if (JUMP_P (insn) + || (NONJUMP_INSN_P (insn) + && (!single_succ_p (bb) + || single_succ_edge (bb)->flags & EDGE_ABNORMAL))) + { +#ifdef HAVE_cc0 + rtx note; +#endif + /* If this is a jump table, then we can't insert stuff here. Since + we know the previous real insn must be the tablejump, we insert + the new instruction just before the tablejump. */ + if (GET_CODE (PATTERN (insn)) == ADDR_VEC + || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC) + insn = prev_real_insn (insn); + +#ifdef HAVE_cc0 + /* FIXME: 'twould be nice to call prev_cc0_setter here but it aborts + if cc0 isn't set. */ + note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX); + if (note) + insn = XEXP (note, 0); + else + { + rtx maybe_cc0_setter = prev_nonnote_insn (insn); + if (maybe_cc0_setter + && INSN_P (maybe_cc0_setter) + && sets_cc0_p (PATTERN (maybe_cc0_setter))) + insn = maybe_cc0_setter; + } +#endif + /* FIXME: What if something in cc0/jump uses value set in new + insn? */ + new_insn = emit_insn_before_noloc (pat, insn); + } + + /* Likewise if the last insn is a call, as will happen in the presence + of exception handling. */ + else if (CALL_P (insn) + && (!single_succ_p (bb) + || single_succ_edge (bb)->flags & EDGE_ABNORMAL)) + { + /* Keeping in mind SMALL_REGISTER_CLASSES and parameters in registers, + we search backward and place the instructions before the first + parameter is loaded. Do this for everyone for consistency and a + presumption that we'll get better code elsewhere as well. */ + + /* Since different machines initialize their parameter registers + in different orders, assume nothing. Collect the set of all + parameter registers. */ + insn = find_first_parameter_load (insn, BB_HEAD (bb)); + + /* If we found all the parameter loads, then we want to insert + before the first parameter load. + + If we did not find all the parameter loads, then we might have + stopped on the head of the block, which could be a CODE_LABEL. + If we inserted before the CODE_LABEL, then we would be putting + the insn in the wrong basic block. In that case, put the insn + after the CODE_LABEL. Also, respect NOTE_INSN_BASIC_BLOCK. */ + while (LABEL_P (insn) + || NOTE_INSN_BASIC_BLOCK_P (insn)) + insn = NEXT_INSN (insn); + + new_insn = emit_insn_before_noloc (pat, insn); + } + else + new_insn = emit_insn_after_noloc (pat, insn); + + return new_insn; +} + /* Implementation of CFG manipulation for linearized RTL. */ struct cfg_hooks rtl_cfg_hooks = { "rtl", @@ -3119,7 +3024,7 @@ struct cfg_hooks rtl_cfg_hooks = { NULL, /* lv_add_condition_to_bb */ NULL, /* lv_adjust_loop_header_phi*/ NULL, /* extract_cond_bb_edges */ - NULL /* flush_pending_stmts */ + NULL /* flush_pending_stmts */ }; /* Implementation of CFG manipulation for cfg layout RTL, where @@ -3162,6 +3067,5 @@ struct cfg_hooks cfg_layout_rtl_cfg_hooks = { rtl_lv_add_condition_to_bb, /* lv_add_condition_to_bb */ NULL, /* lv_adjust_loop_header_phi*/ rtl_extract_cond_bb_edges, /* extract_cond_bb_edges */ - NULL /* flush_pending_stmts */ + NULL /* flush_pending_stmts */ }; -