/* 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.
#include "toplev.h"
#include "tm_p.h"
#include "obstack.h"
+#include "insn-attr.h"
#include "insn-config.h"
#include "cfglayout.h"
#include "expr.h"
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);
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);
\f
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. */
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;
}
/* Like delete_insn but also purge dead edges from BB. */
+
rtx
delete_insn_and_edges (rtx insn)
{
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);
return 0;
}
-struct tree_opt_pass pass_free_cfg =
+static unsigned int
+rest_of_pass_free_cfg (void)
{
- NULL, /* name */
+#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 =
+{
+ {
+ 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. */
commit_edge_insertions ();
}
-/* Update insns block within BB. */
+/* Update BLOCK_FOR_INSN of insns between BEGIN and END
+ (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. */
-void
-update_bb_for_insn (basic_block bb)
+static void
+update_bb_for_insn_chain (rtx begin, rtx end, basic_block bb)
{
rtx insn;
- for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
- {
- if (!BARRIER_P (insn))
- {
- set_block_for_insn (insn, bb);
- df_insn_change_bb (insn);
- }
- if (insn == BB_END (bb))
- break;
- }
+ end = NEXT_INSN (end);
+ for (insn = begin; insn != end; insn = NEXT_INSN (insn))
+ if (!BARRIER_P (insn))
+ df_insn_change_bb (insn, bb);
}
+
+/* Update BLOCK_FOR_INSN of insns in BB to BB,
+ and notify df of the change. */
+
+void
+update_bb_for_insn (basic_block bb)
+{
+ update_bb_for_insn_chain (BB_HEAD (bb), BB_END (bb), bb);
+}
+
\f
/* Return the INSN immediately following the NOTE_INSN_BASIC_BLOCK
note associated with the BLOCK. */
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 ();
}
{
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)
/* Reassociate the insns of B with A. */
if (!b_empty)
{
- rtx x;
-
- for (x = a_end; x != b_end; x = NEXT_INSN (x))
- {
- set_block_for_insn (x, a);
- df_insn_change_bb (x);
- }
+ update_bb_for_insn_chain (a_end, b_debug_end, a);
- set_block_for_insn (b_end, a);
- df_insn_change_bb (b_end);
-
- 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);
which originally were or were created before jump table are
inside the basic block. */
rtx new_insn = BB_END (src);
- rtx tmp;
- for (tmp = NEXT_INSN (BB_END (src)); tmp != barrier;
- tmp = NEXT_INSN (tmp))
- {
- set_block_for_insn (tmp, src);
- df_insn_change_bb (tmp);
- }
+ update_bb_for_insn_chain (NEXT_INSN (BB_END (src)),
+ PREV_INSN (barrier), src);
NEXT_INSN (PREV_INSN (new_insn)) = NEXT_INSN (new_insn);
PREV_INSN (NEXT_INSN (new_insn)) = PREV_INSN (new_insn);
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
++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
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",
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
&& 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);
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
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)++;
}
if (abnormal_edge_flags)
make_edge (src, target, abnormal_edge_flags);
- df_mark_solutions_dirty ();
+ df_mark_solutions_dirty ();
return new_bb;
}
/* 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;
&& 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);
}
}
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;
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);
{
edge e;
edge_iterator ei;
-
+
fprintf (outf, ";; Start of basic block (");
FOR_EACH_EDGE (e, ei, bb->preds)
fprintf (outf, " %d", e->src->index);
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));
}
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;
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))
}
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))
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)
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. */
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)))
/* 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))
/* 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));
}
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)
{
first = NEXT_INSN (first);
gcc_assert (NOTE_INSN_BASIC_BLOCK_P (first));
BB_HEAD (b) = NULL;
+
+ /* emit_insn_after_noloc doesn't call df_insn_change_bb.
+ We need to explicitly call. */
+ update_bb_for_insn_chain (NEXT_INSN (first),
+ BB_END (b),
+ a);
+
delete_insn (first);
}
/* Otherwise just re-associate the instructions. */
{
rtx insn;
- for (insn = BB_HEAD (b);
- insn != NEXT_INSN (BB_END (b));
- insn = NEXT_INSN (insn))
- {
- set_block_for_insn (insn, a);
- df_insn_change_bb (insn);
- }
+ update_bb_for_insn_chain (BB_HEAD (b), BB_END (b), a);
insn = BB_HEAD (b);
/* Skip possible DELETED_LABEL insn. */
? NEXT_INSN (BB_END (e->src)) : get_insns (),
NULL_RTX, e->src);
+ if (e->dest == EXIT_BLOCK_PTR)
+ BB_COPY_PARTITION (new_bb, e->src);
+ else
+ BB_COPY_PARTITION (new_bb, e->dest);
make_edge (new_bb, e->dest, EDGE_FALLTHRU);
redirect_edge_and_branch_force (e, new_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));
}
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
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 ();
}
}
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)++;