/* 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
Free Software Foundation, Inc.
This file is part of GCC.
}
/* Like delete_insn but also purge dead edges from BB. */
+
rtx
delete_insn_and_edges (rtx insn)
{
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));
+}
\f
/* Create a new basic block consisting of the instructions between HEAD and END
inclusive. This function is designed to allow fast BB construction - reuses
return 0;
}
-struct tree_opt_pass pass_free_cfg =
+struct rtl_opt_pass pass_free_cfg =
{
+ {
+ RTL_PASS,
NULL, /* name */
NULL, /* gate */
free_bb_for_insn, /* execute */
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. */
/* 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);
- }
-
- set_block_for_insn (b_end, a);
- df_insn_change_bb (b_end);
+ update_bb_for_insn_chain (a_end, b_end, a);
a_end = b_end;
}
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);
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);