X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcfgrtl.c;h=13e0e5c40d6c5242b9440640dde1f49659d718d4;hb=5632bff570a3489804e448af25abf1db374c6762;hp=1b9c5057162f0d0997c0efe7b7480caf467166a2;hpb=f41d46831f9aff6cf6411e21bb0b4f5dedd192de;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 1b9c5057162..13e0e5c40d6 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -1,6 +1,6 @@ /* Control flow graph manipulation code for GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see #include "toplev.h" #include "tm_p.h" #include "obstack.h" +#include "insn-attr.h" #include "insn-config.h" #include "cfglayout.h" #include "expr.h" @@ -64,7 +65,6 @@ along with GCC; see the file COPYING3. If not see static int can_delete_note_p (const_rtx); static int can_delete_label_p (const_rtx); -static void commit_one_edge_insertion (edge); static basic_block rtl_split_edge (edge); static bool rtl_move_block_after (basic_block, basic_block); static int rtl_verify_flow_info (void); @@ -76,7 +76,7 @@ static void rtl_delete_block (basic_block); static basic_block rtl_redirect_edge_and_branch_force (edge, basic_block); 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 void rtl_dump_bb (basic_block, FILE *, int, int); static int rtl_verify_flow_info_1 (void); static void rtl_make_forwarder_block (edge); @@ -86,8 +86,16 @@ static void rtl_make_forwarder_block (edge); static int can_delete_note_p (const_rtx note) { - return (NOTE_KIND (note) == NOTE_INSN_DELETED - || NOTE_KIND (note) == NOTE_INSN_BASIC_BLOCK); + switch (NOTE_KIND (note)) + { + case NOTE_INSN_DELETED: + case NOTE_INSN_BASIC_BLOCK: + case NOTE_INSN_EPILOGUE_BEG: + return true; + + default: + return false; + } } /* True if a given label can be deleted. */ @@ -162,9 +170,7 @@ delete_insn (rtx insn) remove_note (insn, note); } - if (JUMP_P (insn) - && (GET_CODE (PATTERN (insn)) == ADDR_VEC - || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)) + if (JUMP_TABLE_DATA_P (insn)) { rtx pat = PATTERN (insn); int diff_vec_p = GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC; @@ -232,22 +238,6 @@ delete_insn_chain (rtx start, rtx finish, bool clear_bb) start = next; } } - -/* Like delete_insn_chain but also purge dead edges from BB. */ - -void -delete_insn_chain_and_edges (rtx first, rtx last) -{ - bool purge = false; - - if (INSN_P (last) - && BLOCK_FOR_INSN (last) - && BB_END (BLOCK_FOR_INSN (last)) == last) - purge = true; - delete_insn_chain (first, last, false); - if (purge) - purge_dead_edges (BLOCK_FOR_INSN (last)); -} /* Create a new basic block consisting of the instructions between HEAD and END inclusive. This function is designed to allow fast BB construction - reuses @@ -379,8 +369,6 @@ rtl_delete_block (basic_block b) label for an exception handler which can't be reached. We need to remove the label from the exception_handler_label list. */ insn = BB_HEAD (b); - if (LABEL_P (insn)) - maybe_remove_eh_handler (insn); end = get_last_bb_insn (b); @@ -427,21 +415,37 @@ free_bb_for_insn (void) return 0; } -struct tree_opt_pass pass_free_cfg = +static unsigned int +rest_of_pass_free_cfg (void) +{ +#ifdef DELAY_SLOTS + /* The resource.c machinery uses DF but the CFG isn't guaranteed to be + valid at that point so it would be too late to call df_analyze. */ + if (optimize > 0 && flag_delayed_branch) + df_analyze (); +#endif + + free_bb_for_insn (); + return 0; +} + +struct rtl_opt_pass pass_free_cfg = { - NULL, /* name */ + { + RTL_PASS, + "*free_cfg", /* name */ NULL, /* gate */ - free_bb_for_insn, /* execute */ + rest_of_pass_free_cfg, /* execute */ NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ - 0, /* tv_id */ + TV_NONE, /* tv_id */ 0, /* properties_required */ 0, /* properties_provided */ PROP_cfg, /* properties_destroyed */ 0, /* todo_flags_start */ 0, /* todo_flags_finish */ - 0 /* letter */ + } }; /* Return RTX to emit after when we want to emit code on the entry of function. */ @@ -466,7 +470,7 @@ emit_insn_at_entry (rtx insn) } /* Update BLOCK_FOR_INSN of insns between BEGIN and END - (or BARRIER if found) and notify df of the bb change. + (or BARRIER if found) and notify df of the bb change. The insn chain range is inclusive (i.e. both BEGIN and END will be updated. */ @@ -477,13 +481,8 @@ update_bb_for_insn_chain (rtx begin, rtx end, basic_block bb) end = NEXT_INSN (end); for (insn = begin; insn != end; insn = NEXT_INSN (insn)) - { - if (!BARRIER_P (insn)) - { - set_block_for_insn (insn, bb); - df_insn_change_bb (insn); - } - } + if (!BARRIER_P (insn)) + df_insn_change_bb (insn, bb); } /* Update BLOCK_FOR_INSN of insns in BB to BB, @@ -532,7 +531,26 @@ rtl_split_block (basic_block bb, void *insnp) insn = first_insn_after_basic_block_note (bb); if (insn) - insn = PREV_INSN (insn); + { + rtx next = insn; + + insn = PREV_INSN (insn); + + /* If the block contains only debug insns, insn would have + been NULL in a non-debug compilation, and then we'd end + up emitting a DELETED note. For -fcompare-debug + stability, emit the note too. */ + if (insn != BB_END (bb) + && DEBUG_INSN_P (next) + && DEBUG_INSN_P (BB_END (bb))) + { + while (next != BB_END (bb) && DEBUG_INSN_P (next)) + next = NEXT_INSN (next); + + if (next == BB_END (bb)) + emit_note_after (NOTE_INSN_DELETED, next); + } + } else insn = get_last_insn (); } @@ -567,18 +585,18 @@ rtl_merge_blocks (basic_block a, basic_block b) { rtx b_head = BB_HEAD (b), b_end = BB_END (b), a_end = BB_END (a); rtx del_first = NULL_RTX, del_last = NULL_RTX; + rtx b_debug_start = b_end, b_debug_end = b_end; int b_empty = 0; if (dump_file) fprintf (dump_file, "merging block %d into block %d\n", b->index, a->index); + while (DEBUG_INSN_P (b_end)) + b_end = PREV_INSN (b_debug_start = b_end); + /* If there was a CODE_LABEL beginning B, delete it. */ if (LABEL_P (b_head)) { - /* 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) @@ -641,9 +659,21 @@ rtl_merge_blocks (basic_block a, basic_block b) /* Reassociate the insns of B with A. */ if (!b_empty) { - update_bb_for_insn_chain (a_end, b_end, a); + update_bb_for_insn_chain (a_end, b_debug_end, a); - a_end = b_end; + a_end = b_debug_end; + } + else if (b_end != b_debug_end) + { + /* Move any deleted labels and other notes between the end of A + and the debug insns that make up B after the debug insns, + bringing the debug insns into A while keeping the notes after + the end of A. */ + if (NEXT_INSN (a_end) != b_debug_start) + reorder_insns_nobb (NEXT_INSN (a_end), PREV_INSN (b_debug_start), + b_debug_end); + update_bb_for_insn_chain (b_debug_start, b_debug_end, a); + a_end = b_debug_end; } df_bb_delete (b->index); @@ -881,31 +911,25 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout) return e; } -/* Redirect edge representing branch of (un)conditional jump or tablejump, - NULL on failure */ -static edge -redirect_branch_edge (edge e, basic_block target) +/* Subroutine of redirect_branch_edge that tries to patch the jump + instruction INSN so that it reaches block NEW. Do this + only when it originally reached block OLD. Return true if this + worked or the original target wasn't OLD, return false if redirection + doesn't work. */ + +static bool +patch_jump_insn (rtx insn, rtx old_label, basic_block new_bb) { rtx tmp; - rtx old_label = BB_HEAD (e->dest); - basic_block src = e->src; - rtx insn = BB_END (src); - - /* We can only redirect non-fallthru edges of jump insn. */ - if (e->flags & EDGE_FALLTHRU) - return NULL; - else if (!JUMP_P (insn)) - return NULL; - /* Recognize a tablejump and adjust all matching cases. */ if (tablejump_p (insn, NULL, &tmp)) { rtvec vec; int j; - rtx new_label = block_label (target); + rtx new_label = block_label (new_bb); - if (target == EXIT_BLOCK_PTR) - return NULL; + if (new_bb == EXIT_BLOCK_PTR) + return false; if (GET_CODE (PATTERN (tmp)) == ADDR_VEC) vec = XVEC (PATTERN (tmp), 0); else @@ -932,6 +956,45 @@ redirect_branch_edge (edge e, basic_block target) ++LABEL_NUSES (new_label); } } + else if ((tmp = extract_asm_operands (PATTERN (insn))) != NULL) + { + int i, n = ASM_OPERANDS_LABEL_LENGTH (tmp); + rtx new_label, note; + + if (new_bb == EXIT_BLOCK_PTR) + return false; + new_label = block_label (new_bb); + + for (i = 0; i < n; ++i) + { + rtx old_ref = ASM_OPERANDS_LABEL (tmp, i); + gcc_assert (GET_CODE (old_ref) == LABEL_REF); + if (XEXP (old_ref, 0) == old_label) + { + ASM_OPERANDS_LABEL (tmp, i) + = gen_rtx_LABEL_REF (Pmode, new_label); + --LABEL_NUSES (old_label); + ++LABEL_NUSES (new_label); + } + } + + if (JUMP_LABEL (insn) == old_label) + { + JUMP_LABEL (insn) = new_label; + note = find_reg_note (insn, REG_LABEL_TARGET, new_label); + if (note) + remove_note (insn, note); + } + else + { + note = find_reg_note (insn, REG_LABEL_TARGET, old_label); + if (note) + remove_note (insn, note); + if (JUMP_LABEL (insn) != new_label + && !find_reg_note (insn, REG_LABEL_TARGET, new_label)) + add_reg_note (insn, REG_LABEL_TARGET, new_label); + } + } else { /* ?? We may play the games with moving the named labels from @@ -940,20 +1003,55 @@ redirect_branch_edge (edge e, basic_block target) if (computed_jump_p (insn) /* A return instruction can't be redirected. */ || returnjump_p (insn)) - return NULL; - - /* If the insn doesn't go where we think, we're confused. */ - gcc_assert (JUMP_LABEL (insn) == old_label); + return false; - /* If the substitution doesn't succeed, die. This can happen - if the back end emitted unrecognizable instructions or if - target is exit block on some arches. */ - if (!redirect_jump (insn, block_label (target), 0)) + if (!currently_expanding_to_rtl || JUMP_LABEL (insn) == old_label) { - gcc_assert (target == EXIT_BLOCK_PTR); - return NULL; + /* If the insn doesn't go where we think, we're confused. */ + gcc_assert (JUMP_LABEL (insn) == old_label); + + /* If the substitution doesn't succeed, die. This can happen + if the back end emitted unrecognizable instructions or if + target is exit block on some arches. */ + if (!redirect_jump (insn, block_label (new_bb), 0)) + { + gcc_assert (new_bb == EXIT_BLOCK_PTR); + return false; + } } } + return true; +} + + +/* Redirect edge representing branch of (un)conditional jump or tablejump, + NULL on failure */ +static edge +redirect_branch_edge (edge e, basic_block target) +{ + rtx old_label = BB_HEAD (e->dest); + basic_block src = e->src; + rtx insn = BB_END (src); + + /* We can only redirect non-fallthru edges of jump insn. */ + if (e->flags & EDGE_FALLTHRU) + return NULL; + else if (!JUMP_P (insn) && !currently_expanding_to_rtl) + return NULL; + + if (!currently_expanding_to_rtl) + { + if (!patch_jump_insn (insn, old_label, target)) + return NULL; + } + else + /* When expanding this BB might actually contain multiple + jumps (i.e. not yet split by find_many_sub_basic_blocks). + Redirect all of those that match our label. */ + for (insn = BB_HEAD (src); insn != NEXT_INSN (BB_END (src)); + insn = NEXT_INSN (insn)) + if (JUMP_P (insn) && !patch_jump_insn (insn, old_label, target)) + return NULL; if (dump_file) fprintf (dump_file, "Edge %i->%i redirected to %i\n", @@ -1012,6 +1110,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target) rtx note; edge new_edge; int abnormal_edge_flags = 0; + int loc; /* In the case the last instruction is conditional jump to the next instruction, first redirect the jump itself and then continue @@ -1114,11 +1213,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target) && JUMP_P (BB_END (jump_block)) && !any_condjump_p (BB_END (jump_block)) && (EDGE_SUCC (jump_block, 0)->flags & EDGE_CROSSING)) - REG_NOTES (BB_END (jump_block)) = gen_rtx_EXPR_LIST (REG_CROSSING_JUMP, - NULL_RTX, - REG_NOTES - (BB_END - (jump_block))); + add_reg_note (BB_END (jump_block), REG_CROSSING_JUMP, NULL_RTX); /* Wire edge in. */ new_edge = make_edge (e->src, jump_block, EDGE_FALLTHRU); @@ -1134,11 +1229,15 @@ force_nonfallthru_and_redirect (edge e, basic_block target) else jump_block = e->src; + if (e->goto_locus && e->goto_block == NULL) + loc = e->goto_locus; + else + loc = 0; e->flags &= ~EDGE_FALLTHRU; if (target == EXIT_BLOCK_PTR) { #ifdef HAVE_return - emit_jump_insn_after_noloc (gen_return (), BB_END (jump_block)); + emit_jump_insn_after_setloc (gen_return (), BB_END (jump_block), loc); #else gcc_unreachable (); #endif @@ -1146,7 +1245,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target) else { rtx label = block_label (target); - emit_jump_insn_after_noloc (gen_jump (label), BB_END (jump_block)); + emit_jump_insn_after_setloc (gen_jump (label), BB_END (jump_block), loc); JUMP_LABEL (BB_END (jump_block)) = label; LABEL_NUSES (label)++; } @@ -1157,7 +1256,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target) if (abnormal_edge_flags) make_edge (src, target, abnormal_edge_flags); - df_mark_solutions_dirty (); + df_mark_solutions_dirty (); return new_bb; } @@ -1337,7 +1436,7 @@ insert_insn_on_edge (rtx pattern, edge e) /* Update the CFG for the instructions queued on edge E. */ -static void +void commit_one_edge_insertion (edge e) { rtx before = NULL_RTX, after = NULL_RTX, insns, tmp, last; @@ -1405,25 +1504,11 @@ commit_one_edge_insertion (edge e) && targetm.have_named_sections && e->src != ENTRY_BLOCK_PTR && BB_PARTITION (e->src) == BB_COLD_PARTITION - && !(e->flags & EDGE_CROSSING)) - { - rtx bb_note, cur_insn; - - bb_note = NULL_RTX; - for (cur_insn = BB_HEAD (bb); cur_insn != NEXT_INSN (BB_END (bb)); - cur_insn = NEXT_INSN (cur_insn)) - if (NOTE_INSN_BASIC_BLOCK_P (cur_insn)) - { - bb_note = cur_insn; - break; - } - - 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 - (REG_CROSSING_JUMP, NULL_RTX, REG_NOTES (BB_END (bb))); - } + && !(e->flags & EDGE_CROSSING) + && JUMP_P (after) + && !any_condjump_p (after) + && (single_succ_edge (bb)->flags & EDGE_CROSSING)) + add_reg_note (after, REG_CROSSING_JUMP, NULL_RTX); } } @@ -1518,7 +1603,7 @@ commit_edge_insertions (void) at start and end). */ static void -rtl_dump_bb (basic_block bb, FILE *outf, int indent) +rtl_dump_bb (basic_block bb, FILE *outf, int indent, int flags ATTRIBUTE_UNUSED) { rtx insn; rtx last; @@ -1527,7 +1612,7 @@ rtl_dump_bb (basic_block bb, FILE *outf, int indent) s_indent = (char *) alloca ((size_t) indent + 1); memset (s_indent, ' ', (size_t) indent); s_indent[indent] = '\0'; - + if (df) { df_dump_top (bb, outf); @@ -1594,7 +1679,7 @@ print_rtl_with_bb (FILE *outf, const_rtx rtx_first) { edge e; edge_iterator ei; - + fprintf (outf, ";; Start of basic block ("); FOR_EACH_EDGE (e, ei, bb->preds) fprintf (outf, " %d", e->src->index); @@ -1654,10 +1739,10 @@ print_rtl_with_bb (FILE *outf, const_rtx rtx_first) free (in_bb_p); } - if (current_function_epilogue_delay_list != 0) + if (crtl->epilogue_delay_list != 0) { fprintf (outf, "\n;; Insns in epilogue delay list:\n\n"); - for (tmp_rtx = current_function_epilogue_delay_list; tmp_rtx != 0; + for (tmp_rtx = crtl->epilogue_delay_list; tmp_rtx != 0; tmp_rtx = XEXP (tmp_rtx, 1)) print_rtl_single (outf, XEXP (tmp_rtx, 0)); } @@ -1688,11 +1773,11 @@ get_last_bb_insn (basic_block bb) end = tmp; /* Include any barriers that may follow the basic block. */ - tmp = next_nonnote_insn (end); + tmp = next_nonnote_insn_bb (end); while (tmp && BARRIER_P (tmp)) { end = tmp; - tmp = next_nonnote_insn (end); + tmp = next_nonnote_insn_bb (end); } return end; @@ -1814,12 +1899,16 @@ rtl_verify_flow_info_1 (void) n_abnormal++; } - if (n_eh && GET_CODE (PATTERN (BB_END (bb))) != RESX - && !find_reg_note (BB_END (bb), REG_EH_REGION, NULL_RTX)) + if (n_eh && !find_reg_note (BB_END (bb), REG_EH_REGION, NULL_RTX)) { error ("missing REG_EH_REGION note in the end of bb %i", bb->index); err = 1; } + if (n_eh > 1) + { + error ("too many eh edges %i", bb->index); + err = 1; + } if (n_branch && (!JUMP_P (BB_END (bb)) || (n_branch > 1 && (any_uncondjump_p (BB_END (bb)) @@ -1835,7 +1924,8 @@ rtl_verify_flow_info_1 (void) } if (n_branch != 1 && any_uncondjump_p (BB_END (bb))) { - error ("wrong amount of branch edges after unconditional jump %i", bb->index); + error ("wrong number of branch edges after unconditional jump %i", + bb->index); err = 1; } if (n_branch != 1 && any_condjump_p (BB_END (bb)) @@ -2020,15 +2110,17 @@ rtl_verify_flow_info (void) rtx insn; /* Ensure existence of barrier in BB with no fallthru edges. */ - for (insn = BB_END (bb); !insn || !BARRIER_P (insn); - insn = NEXT_INSN (insn)) - if (!insn - || NOTE_INSN_BASIC_BLOCK_P (insn)) + for (insn = NEXT_INSN (BB_END (bb)); ; insn = NEXT_INSN (insn)) + { + if (!insn || NOTE_INSN_BASIC_BLOCK_P (insn)) { error ("missing barrier after block %i", bb->index); err = 1; break; } + if (BARRIER_P (insn)) + break; + } } else if (e->src != ENTRY_BLOCK_PTR && e->dest != EXIT_BLOCK_PTR) @@ -2096,9 +2188,7 @@ rtl_verify_flow_info (void) case CODE_LABEL: /* An addr_vec is placed outside any basic block. */ if (NEXT_INSN (x) - && JUMP_P (NEXT_INSN (x)) - && (GET_CODE (PATTERN (NEXT_INSN (x))) == ADDR_DIFF_VEC - || GET_CODE (PATTERN (NEXT_INSN (x))) == ADDR_VEC)) + && JUMP_TABLE_DATA_P (NEXT_INSN (x))) x = NEXT_INSN (x); /* But in any case, non-deletable labels can appear anywhere. */ @@ -2138,6 +2228,11 @@ purge_dead_edges (basic_block bb) bool found; edge_iterator ei; + if (DEBUG_INSN_P (insn) && insn != BB_HEAD (bb)) + do + insn = PREV_INSN (insn); + while ((DEBUG_INSN_P (insn) || NOTE_P (insn)) && insn != BB_HEAD (bb)); + /* If this instruction cannot trap, remove REG_EH_REGION notes. */ if (NONJUMP_INSN_P (insn) && (note = find_reg_note (insn, REG_EH_REGION, NULL))) @@ -2153,39 +2248,33 @@ 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)); ) { + bool remove = false; + /* 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 (e->flags & EDGE_ABNORMAL_CALL) { - 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; - } + if (!CALL_P (insn)) + remove = true; + else if (can_nonlocal_goto (insn)) + ; + else if ((e->flags & EDGE_EH) && can_throw_internal (insn)) + ; + else + remove = true; } - else if (e->flags & EDGE_ABNORMAL_CALL) + else if (e->flags & EDGE_EH) + remove = !can_throw_internal (insn); + + if (remove) { - if (CALL_P (BB_END (bb)) - && (! (note = find_reg_note (insn, REG_EH_REGION, NULL)) - || INTVAL (XEXP (note, 0)) >= 0)) - { - ei_next (&ei); - continue; - } + remove_edge (e); + df_set_bb_dirty (bb); + purged = true; } else - { - ei_next (&ei); - continue; - } - - remove_edge (e); - df_set_bb_dirty (bb); - purged = true; + ei_next (&ei); } if (JUMP_P (insn)) @@ -2601,10 +2690,6 @@ cfg_layout_merge_blocks (basic_block a, basic_block b) /* If there was a CODE_LABEL beginning B, delete it. */ if (LABEL_P (BB_HEAD (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)); } @@ -2614,6 +2699,34 @@ cfg_layout_merge_blocks (basic_block a, basic_block b) try_redirect_by_replacing_jump (EDGE_SUCC (a, 0), b, true); gcc_assert (!JUMP_P (BB_END (a))); + /* When not optimizing and the edge is the only place in RTL which holds + some unique locus, emit a nop with that locus in between. */ + if (!optimize && EDGE_SUCC (a, 0)->goto_locus) + { + rtx insn = BB_END (a), end = PREV_INSN (BB_HEAD (a)); + int goto_locus = EDGE_SUCC (a, 0)->goto_locus; + + while (insn != end && (!INSN_P (insn) || INSN_LOCATOR (insn) == 0)) + insn = PREV_INSN (insn); + if (insn != end && locator_eq (INSN_LOCATOR (insn), goto_locus)) + goto_locus = 0; + else + { + insn = BB_HEAD (b); + end = NEXT_INSN (BB_END (b)); + while (insn != end && !INSN_P (insn)) + insn = NEXT_INSN (insn); + if (insn != end && INSN_LOCATOR (insn) != 0 + && locator_eq (INSN_LOCATOR (insn), goto_locus)) + goto_locus = 0; + } + if (goto_locus) + { + BB_END (a) = emit_insn_after_noloc (gen_nop (), BB_END (a), a); + INSN_LOCATOR (BB_END (a)) = goto_locus; + } + } + /* Possible line number notes should appear in between. */ if (b->il.rtl->header) { @@ -2723,7 +2836,8 @@ rtl_block_ends_with_call_p (basic_block bb) while (!CALL_P (insn) && insn != BB_HEAD (bb) && (keep_with_call_p (insn) - || NOTE_P (insn))) + || NOTE_P (insn) + || DEBUG_INSN_P (insn))) insn = PREV_INSN (insn); return (CALL_P (insn)); } @@ -2748,7 +2862,7 @@ need_fake_edge_p (const_rtx insn) if ((CALL_P (insn) && !SIBLING_CALL_P (insn) && !find_reg_note (insn, REG_NORETURN, NULL) - && !CONST_OR_PURE_CALL_P (insn))) + && !(RTL_CONST_OR_PURE_CALL_P (insn)))) return true; return ((GET_CODE (PATTERN (insn)) == ASM_OPERANDS @@ -2812,7 +2926,7 @@ rtl_flow_call_edges_add (sbitmap blocks) e = find_edge (bb, EXIT_BLOCK_PTR); if (e) { - insert_insn_on_edge (gen_rtx_USE (VOIDmode, const0_rtx), e); + insert_insn_on_edge (gen_use (const0_rtx), e); commit_edge_insertions (); } } @@ -2911,7 +3025,7 @@ rtl_lv_add_condition_to_bb (basic_block first_head , op0 = force_operand (op0, NULL_RTX); op1 = force_operand (op1, NULL_RTX); do_compare_rtx_and_jump (op0, op1, comp, 0, - mode, NULL_RTX, NULL_RTX, label); + mode, NULL_RTX, NULL_RTX, label, -1); jump = get_last_insn (); JUMP_LABEL (jump) = label; LABEL_NUSES (label)++;