/* Control flow graph building code for GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
+ Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* find_basic_blocks divides the current function's rtl into basic
blocks and constructs the CFG. The blocks are recorded in the
Available functionality:
- CFG construction
- find_basic_blocks */
+ find_basic_blocks */
\f
#include "config.h"
#include "system.h"
#include "toplev.h"
#include "timevar.h"
-static int count_basic_blocks (rtx);
+static int count_basic_blocks (const_rtx);
static void find_basic_blocks_1 (rtx);
static void make_edges (basic_block, basic_block, int);
static void make_label_edge (sbitmap, basic_block, rtx, int);
block. */
bool
-inside_basic_block_p (rtx insn)
+inside_basic_block_p (const_rtx insn)
{
switch (GET_CODE (insn))
{
the basic block. */
bool
-control_flow_insn_p (rtx insn)
+control_flow_insn_p (const_rtx insn)
{
rtx note;
|| can_throw_internal (insn));
case INSN:
+ /* Treat trap instructions like noreturn calls (same provision). */
+ if (GET_CODE (PATTERN (insn)) == TRAP_IF
+ && XEXP (PATTERN (insn), 0) == const1_rtx)
+ return true;
+
return (flag_non_call_exceptions && can_throw_internal (insn));
case BARRIER:
/* It is nonsense to reach barrier when looking for the
- end of basic block, but before dead code is eliminated
- this may happen. */
+ end of basic block, but before dead code is eliminated
+ this may happen. */
return false;
default:
/* Count the basic blocks of the function. */
static int
-count_basic_blocks (rtx f)
+count_basic_blocks (const_rtx f)
{
int count = NUM_FIXED_BLOCKS;
bool saw_insn = false;
- rtx insn;
+ const_rtx insn;
for (insn = f; insn; insn = NEXT_INSN (insn))
{
/* Code labels and barriers causes current basic block to be
- terminated at previous real insn. */
+ terminated at previous real insn. */
if ((LABEL_P (insn) || BARRIER_P (insn))
&& saw_insn)
count++, saw_insn = false;
check for the edge case of do-nothing functions with no basic blocks. */
if (count == NUM_FIXED_BLOCKS)
{
- emit_insn (gen_rtx_USE (VOIDmode, const0_rtx));
+ emit_use (const0_rtx);
count = NUM_FIXED_BLOCKS + 1;
}
/* Heavy use of computed goto in machine-generated code can lead to
nearly fully-connected CFGs. In that case we spend a significant
amount of time searching the edge lists for duplicates. */
- if (forced_labels || cfun->max_jumptable_ents > 100)
+ if (forced_labels || cfun->cfg->max_jumptable_ents > 100)
edge_cache = sbitmap_alloc (last_basic_block);
/* By nature of the way these get numbered, ENTRY_BLOCK_PTR->next_bb block
while (insn
&& NOTE_P (insn)
- && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
+ && NOTE_KIND (insn) != NOTE_INSN_BASIC_BLOCK)
insn = NEXT_INSN (insn);
if (!insn)
switch (code)
{
case NOTE:
- {
- int kind = NOTE_LINE_NUMBER (insn);
-
- /* Look for basic block notes with which to keep the
- basic_block_info pointers stable. Unthread the note now;
- we'll put it back at the right place in create_basic_block.
- Or not at all if we've already found a note in this block. */
- if (kind == NOTE_INSN_BASIC_BLOCK)
- {
- if (bb_note == NULL_RTX)
- bb_note = insn;
- else
- next = delete_insn (insn);
- }
- break;
- }
+ /* Look for basic block notes with which to keep the
+ basic_block_info pointers stable. Unthread the note now;
+ we'll put it back at the right place in create_basic_block.
+ Or not at all if we've already found a note in this block. */
+ if (NOTE_INSN_BASIC_BLOCK_P (insn))
+ {
+ if (bb_note == NULL_RTX)
+ bb_note = insn;
+ else
+ next = delete_insn (insn);
+ }
+ break;
case CODE_LABEL:
case JUMP_INSN:
actually lay them out. */
basic_block_info = VEC_alloc (basic_block, gc, n_basic_blocks);
- VEC_safe_grow (basic_block, gc, basic_block_info, n_basic_blocks);
- memset (VEC_address (basic_block, basic_block_info), 0,
- sizeof (basic_block) * n_basic_blocks);
+ VEC_safe_grow_cleared (basic_block, gc, basic_block_info, n_basic_blocks);
SET_BASIC_BLOCK (ENTRY_BLOCK, ENTRY_BLOCK_PTR);
SET_BASIC_BLOCK (EXIT_BLOCK, EXIT_BLOCK_PTR);
for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
{
if (FULL_STATE (e->dest) & BLOCK_USED_BY_TABLEJUMP)
- SET_STATE (e->dest, FULL_STATE (e->dest)
- & ~(size_t) BLOCK_USED_BY_TABLEJUMP);
+ SET_STATE (e->dest, FULL_STATE (e->dest)
+ & ~(size_t) BLOCK_USED_BY_TABLEJUMP);
else if (!(e->flags & (EDGE_ABNORMAL | EDGE_EH)))
- {
- remove_edge (e);
- continue;
- }
+ {
+ remove_edge (e);
+ continue;
+ }
ei_next (&ei);
}
}
{
basic_block orig_bb = bb;
rtx insn = BB_HEAD (bb);
- rtx end = BB_END (bb);
+ rtx end = BB_END (bb), x;
rtx table;
rtx flow_transfer_insn = NULL_RTX;
edge fallthru = NULL;
{
fallthru = split_block (bb, PREV_INSN (insn));
if (flow_transfer_insn)
- BB_END (bb) = flow_transfer_insn;
+ {
+ BB_END (bb) = flow_transfer_insn;
+
+ /* Clean up the bb field for the insns between the blocks. */
+ for (x = NEXT_INSN (flow_transfer_insn);
+ x != BB_HEAD (fallthru->dest);
+ x = NEXT_INSN (x))
+ if (!BARRIER_P (x))
+ set_block_for_insn (x, NULL);
+ }
bb = fallthru->dest;
remove_edge (fallthru);
{
fallthru = split_block (bb, PREV_INSN (insn));
BB_END (bb) = flow_transfer_insn;
+
+ /* Clean up the bb field for the insns between the blocks. */
+ for (x = NEXT_INSN (flow_transfer_insn);
+ x != BB_HEAD (fallthru->dest);
+ x = NEXT_INSN (x))
+ if (!BARRIER_P (x))
+ set_block_for_insn (x, NULL);
+
bb = fallthru->dest;
remove_edge (fallthru);
flow_transfer_insn = NULL_RTX;
return and barrier, or possibly other sequence not behaving like
ordinary jump, we need to take care and move basic block boundary. */
if (flow_transfer_insn)
- BB_END (bb) = flow_transfer_insn;
+ {
+ BB_END (bb) = flow_transfer_insn;
+
+ /* Clean up the bb field for the insns that do not belong to BB. */
+ x = flow_transfer_insn;
+ while (x != end)
+ {
+ x = NEXT_INSN (x);
+ if (!BARRIER_P (x))
+ set_block_for_insn (x, NULL);
+ }
+ }
/* We've possibly replaced the conditional jump by conditional jump
followed by cleanup at fallthru edge, so the outgoing edges may