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, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* This file contains low level functions to manipulate the CFG and analyze it
that are aware of the RTL intermediate language.
#include "expr.h"
#include "target.h"
#include "cfgloop.h"
-
-/* The labels mentioned in non-jump rtl. Valid during find_basic_blocks. */
-/* ??? Should probably be using LABEL_NUSES instead. It would take a
- bit of surgery to be able to use or co-opt the routines in jump. */
-rtx label_value_list;
+#include "ggc.h"
static int can_delete_note_p (rtx);
static int can_delete_label_p (rtx);
return (!LABEL_PRESERVE_P (label)
/* User declared labels must be preserved. */
&& LABEL_NAME (label) == 0
- && !in_expr_list_p (forced_labels, label)
- && !in_expr_list_p (label_value_list, label));
+ && !in_expr_list_p (forced_labels, label));
}
/* Delete INSN by patching it out. Return the next insn. */
bb = alloc_block ();
+ init_rtl_bb_info (bb);
if (!head && !end)
head = end = bb_note
= emit_note_after (NOTE_INSN_BASIC_BLOCK, get_last_insn ());
BB_HEAD (bb) = head;
BB_END (bb) = end;
bb->index = last_basic_block++;
- bb->flags = BB_NEW;
+ bb->flags = BB_NEW | BB_RTL;
link_block (bb, after);
BASIC_BLOCK (bb->index) = bb;
update_bb_for_insn (bb);
{
basic_block newbb = rtl_create_basic_block (head, end, after);
- initialize_bb_rbi (newbb);
return newbb;
}
\f
FOR_EACH_EDGE (e, ei, new_bb->succs)
e->src = new_bb;
- if (bb->global_live_at_start)
+ if (bb->il.rtl->global_live_at_start)
{
- new_bb->global_live_at_start = ALLOC_REG_SET (®_obstack);
- new_bb->global_live_at_end = ALLOC_REG_SET (®_obstack);
- COPY_REG_SET (new_bb->global_live_at_end, bb->global_live_at_end);
+ new_bb->il.rtl->global_live_at_start = ALLOC_REG_SET (®_obstack);
+ new_bb->il.rtl->global_live_at_end = ALLOC_REG_SET (®_obstack);
+ COPY_REG_SET (new_bb->il.rtl->global_live_at_end, bb->il.rtl->global_live_at_end);
/* We now have to calculate which registers are live at the end
of the split basic block and at the start of the new basic
block. Start with those registers that are known to be live
at the end of the original basic block and get
propagate_block to determine which registers are live. */
- COPY_REG_SET (new_bb->global_live_at_start, bb->global_live_at_end);
- propagate_block (new_bb, new_bb->global_live_at_start, NULL, NULL, 0);
- COPY_REG_SET (bb->global_live_at_end,
- new_bb->global_live_at_start);
+ COPY_REG_SET (new_bb->il.rtl->global_live_at_start, bb->il.rtl->global_live_at_end);
+ propagate_block (new_bb, new_bb->il.rtl->global_live_at_start, NULL, NULL, 0);
+ COPY_REG_SET (bb->il.rtl->global_live_at_end,
+ new_bb->il.rtl->global_live_at_start);
#ifdef HAVE_conditional_execution
/* In the presence of conditional execution we are not able to update
liveness precisely. */
}
BB_END (a) = a_end;
+ a->il.rtl->global_live_at_end = b->il.rtl->global_live_at_end;
}
/* Return true when block A and B can be merged. */
/* Selectively unlink whole insn chain. */
if (in_cfglayout)
{
- rtx insn = src->rbi->footer;
+ rtx insn = src->il.rtl->footer;
delete_insn_chain (kill_from, BB_END (src));
if (PREV_INSN (insn))
NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
else
- src->rbi->footer = NEXT_INSN (insn);
+ src->il.rtl->footer = NEXT_INSN (insn);
if (NEXT_INSN (insn))
PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
}
jump_block->frequency = EDGE_FREQUENCY (e);
jump_block->loop_depth = target->loop_depth;
- if (target->global_live_at_start)
+ if (target->il.rtl->global_live_at_start)
{
- jump_block->global_live_at_start = ALLOC_REG_SET (®_obstack);
- jump_block->global_live_at_end = ALLOC_REG_SET (®_obstack);
- COPY_REG_SET (jump_block->global_live_at_start,
- target->global_live_at_start);
- COPY_REG_SET (jump_block->global_live_at_end,
- target->global_live_at_start);
+ jump_block->il.rtl->global_live_at_start = ALLOC_REG_SET (®_obstack);
+ jump_block->il.rtl->global_live_at_end = ALLOC_REG_SET (®_obstack);
+ COPY_REG_SET (jump_block->il.rtl->global_live_at_start,
+ target->il.rtl->global_live_at_start);
+ COPY_REG_SET (jump_block->il.rtl->global_live_at_end,
+ target->il.rtl->global_live_at_start);
}
/* Make sure new block ends up in correct hot/cold section. */
/* ??? In a late-running flow pass, other folks may have deleted basic
blocks by nopping out blocks, leaving multiple BARRIERs between here
- and the target label. They ought to be chastized and fixed.
+ and the target label. They ought to be chastised and fixed.
We can also wind up with a sequence of undeletable labels between
one block and the next.
}
/* ??? This info is likely going to be out of date very soon. */
- if (edge_in->dest->global_live_at_start)
+ if (edge_in->dest->il.rtl->global_live_at_start)
{
- bb->global_live_at_start = ALLOC_REG_SET (®_obstack);
- bb->global_live_at_end = ALLOC_REG_SET (®_obstack);
- COPY_REG_SET (bb->global_live_at_start,
- edge_in->dest->global_live_at_start);
- COPY_REG_SET (bb->global_live_at_end,
- edge_in->dest->global_live_at_start);
+ bb->il.rtl->global_live_at_start = ALLOC_REG_SET (®_obstack);
+ bb->il.rtl->global_live_at_end = ALLOC_REG_SET (®_obstack);
+ COPY_REG_SET (bb->il.rtl->global_live_at_start,
+ edge_in->dest->il.rtl->global_live_at_start);
+ COPY_REG_SET (bb->il.rtl->global_live_at_end,
+ edge_in->dest->il.rtl->global_live_at_start);
}
make_single_succ_edge (bb, edge_in->dest, EDGE_FALLTHRU);
&& !REGNO_PTR_FRAME_P (regno))
SET_REGNO_REG_SET (killed, regno);
- bitmap_and_into (killed, e->dest->global_live_at_start);
+ bitmap_and_into (killed, e->dest->il.rtl->global_live_at_start);
EXECUTE_IF_SET_IN_REG_SET (killed, 0, regno, rsi)
{
s_indent[indent] = '\0';
fprintf (outf, ";;%s Registers live at start: ", s_indent);
- dump_regset (bb->global_live_at_start, outf);
+ dump_regset (bb->il.rtl->global_live_at_start, outf);
putc ('\n', outf);
for (insn = BB_HEAD (bb), last = NEXT_INSN (BB_END (bb)); insn != last;
print_rtl_single (outf, insn);
fprintf (outf, ";;%s Registers live at end: ", s_indent);
- dump_regset (bb->global_live_at_end, outf);
+ dump_regset (bb->il.rtl->global_live_at_end, outf);
putc ('\n', outf);
}
\f
{
fprintf (outf, ";; Start of basic block %d, registers live:",
bb->index);
- dump_regset (bb->global_live_at_start, outf);
+ dump_regset (bb->il.rtl->global_live_at_start, outf);
putc ('\n', outf);
}
{
fprintf (outf, ";; End of basic block %d, registers live:\n",
bb->index);
- dump_regset (bb->global_live_at_end, outf);
+ dump_regset (bb->il.rtl->global_live_at_end, outf);
putc ('\n', outf);
}
if (x == end)
break;
+ if (!(bb->flags & BB_RTL))
+ {
+ error ("BB_RTL flag not set for block %d", bb->index);
+ err = 1;
+ }
+
if (!x)
{
error ("end insn %d for block %d not found in the insn stream",
edge e;
edge_iterator ei;
+ if (bb->predictions)
+ {
+ error ("bb prediction set for block %i, but it is not used in RTL land", bb->index);
+ err = 1;
+ }
+
FOR_EACH_EDGE (e, ei, bb->succs)
if (e->flags & EDGE_FALLTHRU)
break;
rtx insn = insnp;
basic_block new_bb = rtl_split_block (bb, insn);
- new_bb->rbi->footer = bb->rbi->footer;
- bb->rbi->footer = NULL;
+ new_bb->il.rtl->footer = bb->il.rtl->footer;
+ bb->il.rtl->footer = NULL;
return new_bb;
}
{
rtx insn, next, prev = PREV_INSN (BB_HEAD (bb)), *to, remaints;
- if (bb->rbi->header)
+ if (bb->il.rtl->header)
{
next = BB_HEAD (bb);
if (prev)
- NEXT_INSN (prev) = bb->rbi->header;
+ NEXT_INSN (prev) = bb->il.rtl->header;
else
- set_first_insn (bb->rbi->header);
- PREV_INSN (bb->rbi->header) = prev;
- insn = bb->rbi->header;
+ set_first_insn (bb->il.rtl->header);
+ PREV_INSN (bb->il.rtl->header) = prev;
+ insn = bb->il.rtl->header;
while (NEXT_INSN (insn))
insn = NEXT_INSN (insn);
NEXT_INSN (insn) = next;
PREV_INSN (next) = insn;
}
next = NEXT_INSN (BB_END (bb));
- if (bb->rbi->footer)
+ if (bb->il.rtl->footer)
{
- insn = bb->rbi->footer;
+ insn = bb->il.rtl->footer;
while (insn)
{
if (BARRIER_P (insn))
if (PREV_INSN (insn))
NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
else
- bb->rbi->footer = NEXT_INSN (insn);
+ bb->il.rtl->footer = NEXT_INSN (insn);
if (NEXT_INSN (insn))
PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
}
break;
insn = NEXT_INSN (insn);
}
- if (bb->rbi->footer)
+ if (bb->il.rtl->footer)
{
insn = BB_END (bb);
- NEXT_INSN (insn) = bb->rbi->footer;
- PREV_INSN (bb->rbi->footer) = insn;
+ NEXT_INSN (insn) = bb->il.rtl->footer;
+ PREV_INSN (bb->il.rtl->footer) = insn;
while (NEXT_INSN (insn))
insn = NEXT_INSN (insn);
NEXT_INSN (insn) = next;
}
}
if (bb->next_bb != EXIT_BLOCK_PTR)
- to = &bb->next_bb->rbi->header;
+ to = &bb->next_bb->il.rtl->header;
else
to = &cfg_layout_function_footer;
- bb->rbi = NULL;
-
rtl_delete_block (bb);
if (prev)
gcc_assert (!JUMP_P (BB_END (a)));
/* Possible line number notes should appear in between. */
- if (b->rbi->header)
+ if (b->il.rtl->header)
{
rtx first = BB_END (a), last;
- last = emit_insn_after_noloc (b->rbi->header, BB_END (a));
+ last = emit_insn_after_noloc (b->il.rtl->header, BB_END (a));
delete_insn_chain (NEXT_INSN (first), last);
- b->rbi->header = NULL;
+ b->il.rtl->header = NULL;
}
/* In the case basic blocks are not adjacent, move them around. */
}
/* Possible tablejumps and barriers should appear after the block. */
- if (b->rbi->footer)
+ if (b->il.rtl->footer)
{
- if (!a->rbi->footer)
- a->rbi->footer = b->rbi->footer;
+ if (!a->il.rtl->footer)
+ a->il.rtl->footer = b->il.rtl->footer;
else
{
- rtx last = a->rbi->footer;
+ rtx last = a->il.rtl->footer;
while (NEXT_INSN (last))
last = NEXT_INSN (last);
- NEXT_INSN (last) = b->rbi->footer;
- PREV_INSN (b->rbi->footer) = last;
+ NEXT_INSN (last) = b->il.rtl->footer;
+ PREV_INSN (b->il.rtl->footer) = last;
}
- b->rbi->footer = NULL;
+ b->il.rtl->footer = NULL;
}
+ a->il.rtl->global_live_at_end = b->il.rtl->global_live_at_end;
if (dump_file)
fprintf (dump_file, "Merged blocks %d and %d.\n",
/* ??? This info is likely going to be out of date very soon, but we must
create it to avoid getting an ICE later. */
- if (e->dest->global_live_at_start)
+ if (e->dest->il.rtl->global_live_at_start)
{
- new_bb->global_live_at_start = ALLOC_REG_SET (®_obstack);
- new_bb->global_live_at_end = ALLOC_REG_SET (®_obstack);
- COPY_REG_SET (new_bb->global_live_at_start,
- e->dest->global_live_at_start);
- COPY_REG_SET (new_bb->global_live_at_end,
- e->dest->global_live_at_start);
+ new_bb->il.rtl->global_live_at_start = ALLOC_REG_SET (®_obstack);
+ new_bb->il.rtl->global_live_at_end = ALLOC_REG_SET (®_obstack);
+ COPY_REG_SET (new_bb->il.rtl->global_live_at_start,
+ e->dest->il.rtl->global_live_at_start);
+ COPY_REG_SET (new_bb->il.rtl->global_live_at_end,
+ e->dest->il.rtl->global_live_at_start);
}
make_edge (new_bb, e->dest, EDGE_FALLTHRU);
}
}
+void
+init_rtl_bb_info (basic_block bb)
+{
+ gcc_assert (!bb->il.rtl);
+ bb->il.rtl = ggc_alloc_cleared (sizeof (struct rtl_bb_info));
+}
+
/* Implementation of CFG manipulation for linearized RTL. */
struct cfg_hooks rtl_cfg_hooks = {