#include "tm.h"
#include "tree.h"
#include "hard-reg-set.h"
+#include "predict.h"
+#include "vec.h"
+#include "hashtab.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "input.h"
+#include "function.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfgrtl.h"
+#include "cfganal.h"
+#include "cfgbuild.h"
+#include "cfgcleanup.h"
#include "basic-block.h"
#include "bb-reorder.h"
#include "regs.h"
#include "flags.h"
-#include "function.h"
#include "except.h"
#include "rtl-error.h"
#include "tm_p.h"
/* Holds the interesting leading and trailing notes for the function.
Only applicable if the CFG is in cfglayout mode. */
-static GTY(()) rtx cfg_layout_function_footer;
-static GTY(()) rtx cfg_layout_function_header;
+static GTY(()) rtx_insn *cfg_layout_function_footer;
+static GTY(()) rtx_insn *cfg_layout_function_header;
static rtx_insn *skip_insns_after_block (basic_block);
static void record_effective_endpoints (void);
/* Delete INSN by patching it out. */
void
-delete_insn (rtx insn)
+delete_insn (rtx uncast_insn)
{
+ rtx_insn *insn = as_a <rtx_insn *> (uncast_insn);
rtx note;
bool really_delete = true;
&& bb == BLOCK_FOR_INSN (bb_note))
{
reorder_insns_nobb (insn, insn, bb_note);
- SET_BB_HEAD (bb) = bb_note;
+ BB_HEAD (bb) = bb_note;
if (BB_END (bb) == bb_note)
- SET_BB_END (bb) = insn;
+ BB_END (bb) = insn;
}
}
- remove_node_from_expr_list (insn, &nonlocal_goto_handler_labels);
+ remove_node_from_insn_list (insn, &nonlocal_goto_handler_labels);
}
if (really_delete)
{
/* If this insn has already been deleted, something is very wrong. */
- gcc_assert (!INSN_DELETED_P (insn));
+ gcc_assert (!insn->deleted ());
if (INSN_P (insn))
df_insn_delete (insn);
remove_insn (insn);
- INSN_DELETED_P (insn) = 1;
+ insn->set_deleted ();
}
/* If deleting a jump, decrement the use count of the label. Deleting
remove_note (insn, note);
}
- if (JUMP_TABLE_DATA_P (insn))
+ if (rtx_jump_table_data *table = dyn_cast <rtx_jump_table_data *> (insn))
{
- rtx pat = PATTERN (insn);
- int diff_vec_p = GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC;
- int len = XVECLEN (pat, diff_vec_p);
+ rtvec vec = table->get_labels ();
+ int len = GET_NUM_ELEM (vec);
int i;
for (i = 0; i < len; i++)
{
- rtx label = XEXP (XVECEXP (pat, diff_vec_p, i), 0);
+ rtx label = XEXP (RTVEC_ELT (vec, i), 0);
/* When deleting code in bulk (e.g. removing many unreachable
blocks) we can delete a label that's a target of the vector
/* Like delete_insn but also purge dead edges from BB. */
void
-delete_insn_and_edges (rtx insn)
+delete_insn_and_edges (rtx_insn *insn)
{
bool purge = false;
else
delete_insn (current);
- if (clear_bb && !INSN_DELETED_P (current))
+ if (clear_bb && !current->deleted ())
set_block_for_insn (current, NULL);
if (current == start)
AFTER is the basic block we should be put after. */
basic_block
-create_basic_block_structure (rtx head, rtx end, rtx_note *bb_note,
+create_basic_block_structure (rtx_insn *head, rtx_insn *end, rtx_note *bb_note,
basic_block after)
{
basic_block bb;
{
/* If we found an existing note, thread it back onto the chain. */
- rtx after;
+ rtx_insn *after;
if (LABEL_P (head))
after = head;
if (NEXT_INSN (end) == bb_note)
end = bb_note;
- SET_BB_HEAD (bb) = head;
- SET_BB_END (bb) = end;
+ BB_HEAD (bb) = head;
+ BB_END (bb) = end;
bb->index = last_basic_block_for_fn (cfun)++;
bb->flags = BB_NEW | BB_RTL;
link_block (bb, after);
static basic_block
rtl_create_basic_block (void *headp, void *endp, basic_block after)
{
- rtx head = (rtx) headp, end = (rtx) endp;
+ rtx_insn *head = (rtx_insn *) headp;
+ rtx_insn *end = (rtx_insn *) endp;
basic_block bb;
/* Grow the basic block array if needed. */
end = get_last_bb_insn (b);
/* Selectively delete the entire chain. */
- SET_BB_HEAD (b) = NULL;
+ BB_HEAD (b) = NULL;
delete_insn_chain (insn, end, true);
return NEXT_INSN (insn);
}
-/* Creates a new basic block just after basic block B by splitting
- everything after specified instruction I. */
+/* Creates a new basic block just after basic block BB by splitting
+ everything after specified instruction INSNP. */
static basic_block
rtl_split_block (basic_block bb, void *insnp)
/* Create the new basic block. */
new_bb = create_basic_block (NEXT_INSN (insn), BB_END (bb), bb);
BB_COPY_PARTITION (new_bb, bb);
- SET_BB_END (bb) = insn;
+ BB_END (bb) = insn;
/* Redirect the outgoing edges. */
new_bb->succs = bb->succs;
if (!unique_locus_on_edge_between_p (a, b))
return;
- SET_BB_END (a) = emit_insn_after_noloc (gen_nop (), BB_END (a), a);
+ BB_END (a) = emit_insn_after_noloc (gen_nop (), BB_END (a), a);
INSN_LOCATION (BB_END (a)) = EDGE_SUCC (a, 0)->goto_locus;
}
/* Delete everything marked above as well as crap that might be
hanging out between the two blocks. */
- SET_BB_END (a) = a_end;
- SET_BB_HEAD (b) = b_empty ? NULL_RTX : b_head;
+ BB_END (a) = a_end;
+ BB_HEAD (b) = b_empty ? NULL : b_head;
delete_insn_chain (del_first, del_last, true);
/* When not optimizing and the edge is the only place in RTL which holds
{
update_bb_for_insn_chain (a_end, b_debug_end, a);
- SET_BB_END (a) = b_debug_end;
- SET_BB_HEAD (b) = NULL_RTX;
+ BB_END (a) = b_debug_end;
+ BB_HEAD (b) = NULL;
}
else if (b_end != b_debug_end)
{
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);
- SET_BB_END (a) = b_debug_end;
+ BB_END (a) = b_debug_end;
}
df_bb_delete (b->index);
if (!LABEL_P (BB_HEAD (block)))
{
- SET_BB_HEAD (block) = emit_label_before (gen_label_rtx (), BB_HEAD (block));
+ BB_HEAD (block) = emit_label_before (gen_label_rtx (), BB_HEAD (block));
}
return BB_HEAD (block);
if (new_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
return false;
- if (GET_CODE (PATTERN (table)) == ADDR_VEC)
- vec = XVEC (PATTERN (table), 0);
- else
- vec = XVEC (PATTERN (table), 1);
+ vec = table->get_labels ();
for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
if (XEXP (RTVEC_ELT (vec, j), 0) == old_label)
&& SET_DEST (tmp) == pc_rtx
&& GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
&& GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF
- && XEXP (XEXP (SET_SRC (tmp), 2), 0) == old_label)
+ && LABEL_REF_LABEL (XEXP (SET_SRC (tmp), 2)) == old_label)
{
XEXP (SET_SRC (tmp), 2) = gen_rtx_LABEL_REF (Pmode,
new_label);
gcc_assert (current_ir_type () == IR_RTL_CFGRTL
|| current_ir_type () == IR_RTL_CFGLAYOUT);
if (current_ir_type () == IR_RTL_CFGLAYOUT)
- BB_FOOTER (bb) = unlink_insn_chain (barrier, barrier);
+ {
+ rtx_insn *insn = unlink_insn_chain (barrier, barrier);
+
+ if (BB_FOOTER (bb))
+ {
+ rtx_insn *footer_tail = BB_FOOTER (bb);
+
+ while (NEXT_INSN (footer_tail))
+ footer_tail = NEXT_INSN (footer_tail);
+ if (!BARRIER_P (footer_tail))
+ {
+ SET_NEXT_INSN (footer_tail) = insn;
+ SET_PREV_INSN (insn) = footer_tail;
+ }
+ }
+ else
+ BB_FOOTER (bb) = insn;
+ }
}
/* Like force_nonfallthru below, but additionally performs redirection
if (EDGE_COUNT (e->src->succs) >= 2 || abnormal_edge_flags || asm_goto_edge)
{
+ rtx_insn *new_head;
gcov_type count = e->count;
int probability = e->probability;
/* Create the new structures. */
forward from the last instruction of the old block. */
rtx_jump_table_data *table;
if (tablejump_p (BB_END (e->src), NULL, &table))
- note = table;
+ new_head = table;
else
- note = BB_END (e->src);
- note = NEXT_INSN (note);
+ new_head = BB_END (e->src);
+ new_head = NEXT_INSN (new_head);
- jump_block = create_basic_block (note, NULL, e->src);
+ jump_block = create_basic_block (new_head, NULL, e->src);
jump_block->count = count;
jump_block->frequency = EDGE_FREQUENCY (e);
in dumpfile.h. */
void
-print_rtl_with_bb (FILE *outf, const_rtx rtx_first, int flags)
+print_rtl_with_bb (FILE *outf, const rtx_insn *rtx_first, int flags)
{
- const_rtx tmp_rtx;
+ const rtx_insn *tmp_rtx;
if (rtx_first == 0)
fprintf (outf, "(nil)\n");
else
e = find_fallthru_edge (bb->succs);
stop = NEXT_INSN (BB_END (bb));
- SET_BB_END (bb) = insn;
+ BB_END (bb) = insn;
for (insn = NEXT_INSN (insn); insn != stop; insn = next)
{
if (GET_CODE (PATTERN (insn)) != USE)
{
/* We're not deleting it, we're moving it. */
- INSN_DELETED_P (insn) = 0;
+ insn->set_undeleted ();
SET_PREV_INSN (insn) = NULL_RTX;
SET_NEXT_INSN (insn) = NULL_RTX;
/* Cut the insns from FIRST to LAST out of the insns stream. */
rtx_insn *
-unlink_insn_chain (rtx first, rtx last)
+unlink_insn_chain (rtx_insn *first, rtx_insn *last)
{
rtx_insn *prevfirst = PREV_INSN (first);
rtx_insn *nextlast = NEXT_INSN (last);
set_last_insn (prevfirst);
if (!prevfirst)
set_first_insn (nextlast);
- return as_a <rtx_insn *> (first);
+ return first;
}
\f
/* Skip over inter-block insns occurring after BB which are typically
cfg_layout_function_header =
unlink_insn_chain (get_insns (), PREV_INSN (insn));
else
- cfg_layout_function_header = NULL_RTX;
+ cfg_layout_function_header = NULL;
next_insn = get_insns ();
FOR_EACH_BB_FN (bb, cfun)
rtx_insn *end;
if (PREV_INSN (BB_HEAD (bb)) && next_insn != BB_HEAD (bb))
- SET_BB_HEADER (bb) = unlink_insn_chain (next_insn,
+ BB_HEADER (bb) = unlink_insn_chain (next_insn,
PREV_INSN (BB_HEAD (bb)));
end = skip_insns_after_block (bb);
if (NEXT_INSN (BB_END (bb)) && BB_END (bb) != end)
{
bb->aux = NULL;
if (!stay_in_cfglayout_mode)
- SET_BB_HEADER (bb) = BB_FOOTER (bb) = NULL;
+ BB_HEADER (bb) = BB_FOOTER (bb) = NULL;
}
/* Maybe reset the original copy tables, they are not valid anymore
fixup_reorder_chain (void)
{
basic_block bb;
- rtx insn = NULL;
+ rtx_insn *insn = NULL;
if (cfg_layout_function_header)
{
}
nb = split_edge (e);
if (!INSN_P (BB_END (nb)))
- SET_BB_END (nb) = emit_insn_after_noloc (gen_nop (), BB_END (nb),
+ BB_END (nb) = emit_insn_after_noloc (gen_nop (), BB_END (nb),
nb);
INSN_LOCATION (BB_END (nb)) = e->goto_locus;
}
rtx_insn *
-duplicate_insn_chain (rtx from, rtx to)
+duplicate_insn_chain (rtx_insn *from, rtx_insn *to)
{
- rtx insn, next, copy;
+ rtx_insn *insn, *next, *copy;
rtx_note *last;
/* Avoid updating of boundaries of previous basic block. The
}
insn = NEXT_INSN (last);
delete_insn (last);
- return safe_as_a <rtx_insn *> (insn);
+ return insn;
}
/* Create a duplicate of the basic block BB. */
insn = NEXT_INSN (insn);
insn = duplicate_insn_chain (BB_HEADER (bb), insn);
if (insn)
- SET_BB_HEADER (new_bb) = unlink_insn_chain (insn, get_last_insn ());
+ BB_HEADER (new_bb) = unlink_insn_chain (insn, get_last_insn ());
}
if (BB_FOOTER (bb))
void
cfg_layout_initialize (unsigned int flags)
{
- rtx x;
+ rtx_insn_list *x;
basic_block bb;
/* Once bb partitioning is complete, cfg layout mode should not be
record_effective_endpoints ();
/* Make sure that the targets of non local gotos are marked. */
- for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1))
+ for (x = nonlocal_goto_handler_labels; x; x = x->next ())
{
- bb = BLOCK_FOR_INSN (XEXP (x, 0));
+ bb = BLOCK_FOR_INSN (x->insn ());
bb->flags |= BB_NON_LOCAL_GOTO_TARGET;
}
cfg_layout_delete_block (basic_block bb)
{
rtx_insn *insn, *next, *prev = PREV_INSN (BB_HEAD (bb)), *remaints;
- rtx *to;
+ rtx_insn **to;
if (BB_HEADER (bb))
{
}
}
if (bb->next_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
- to = &SET_BB_HEADER (bb->next_bb);
+ to = &BB_HEADER (bb->next_bb);
else
to = &cfg_layout_function_footer;
SET_PREV_INSN (BB_FOOTER (a)) = last;
BB_FOOTER (a) = BB_HEADER (b);
}
- SET_BB_HEADER (b) = NULL;
+ BB_HEADER (b) = NULL;
}
/* In the case basic blocks are not adjacent, move them around. */
else
{
insn = BB_HEAD (b);
- SET_BB_END (a) = BB_END (b);
+ BB_END (a) = BB_END (b);
}
/* emit_insn_after_noloc doesn't call df_insn_change_bb.
if (!NOTE_INSN_BASIC_BLOCK_P (insn))
insn = NEXT_INSN (insn);
gcc_assert (NOTE_INSN_BASIC_BLOCK_P (insn));
- SET_BB_HEAD (b) = SET_BB_END (b) = NULL;
+ BB_HEAD (b) = BB_END (b) = NULL;
delete_insn (insn);
df_bb_delete (b->index);
rtx op0 = XEXP ((rtx)comp_rtx, 0);
rtx op1 = XEXP ((rtx)comp_rtx, 1);
enum rtx_code comp = GET_CODE ((rtx)comp_rtx);
- enum machine_mode mode;
+ machine_mode mode;
label = block_label (first_head);
seq = get_insns ();
end_sequence ();
- /* Add the new cond , in the new head. */
+ /* Add the new cond, in the new head. */
emit_insn_after (seq, BB_END (cond_bb));
}
rtl_account_profile_record,
};
-/* BB_HEAD as an rvalue. */
-
-rtx_insn *BB_HEAD (const_basic_block bb)
-{
- rtx insn = bb->il.x.head_;
- return safe_as_a <rtx_insn *> (insn);
-}
-
-/* BB_HEAD for use as an lvalue. */
-
-rtx& SET_BB_HEAD (basic_block bb)
-{
- return bb->il.x.head_;
-}
-
-/* BB_END as an rvalue. */
-
-rtx_insn *BB_END (const_basic_block bb)
-{
- rtx insn = bb->il.x.rtl->end_;
- return safe_as_a <rtx_insn *> (insn);
-}
-
-/* BB_END as an lvalue. */
-
-rtx& SET_BB_END (basic_block bb)
-{
- return bb->il.x.rtl->end_;
-}
-
-/* BB_HEADER as an rvalue. */
-
-rtx_insn *BB_HEADER (const_basic_block bb)
-{
- rtx insn = bb->il.x.rtl->header_;
- return safe_as_a <rtx_insn *> (insn);
-}
-
-/* BB_HEADER as an lvalue. */
-
-rtx& SET_BB_HEADER (basic_block bb)
-{
- return bb->il.x.rtl->header_;
-}
-
#include "gt-cfgrtl.h"