/* Control flow graph manipulation code for GNU compiler.
- Copyright (C) 1987-2014 Free Software Foundation, Inc.
+ Copyright (C) 1987-2015 Free Software Foundation, Inc.
This file is part of GCC.
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "alias.h"
+#include "symtab.h"
#include "tree.h"
#include "hard-reg-set.h"
+#include "predict.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"
#include "obstack.h"
#include "insn-attr.h"
#include "insn-config.h"
+#include "rtl.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "varasm.h"
+#include "stmt.h"
#include "expr.h"
#include "target.h"
#include "common/common-target.h"
#include "cfgloop.h"
-#include "ggc.h"
#include "tree-pass.h"
#include "df.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 skip_insns_after_block (basic_block);
+static rtx_insn *skip_insns_after_block (basic_block);
static void record_effective_endpoints (void);
-static rtx label_for_bb (basic_block);
static void fixup_reorder_chain (void);
void verify_insn_chain (void);
static void fixup_fallthru_exit_predecessor (void);
-static int can_delete_note_p (const_rtx);
-static int can_delete_label_p (const_rtx);
+static int can_delete_note_p (const rtx_note *);
+static int can_delete_label_p (const rtx_code_label *);
static basic_block rtl_split_edge (edge);
static bool rtl_move_block_after (basic_block, basic_block);
static int rtl_verify_flow_info (void);
so that we may simply delete it. */
static int
-can_delete_note_p (const_rtx note)
+can_delete_note_p (const rtx_note *note)
{
switch (NOTE_KIND (note))
{
/* True if a given label can be deleted. */
static int
-can_delete_label_p (const_rtx label)
+can_delete_label_p (const rtx_code_label *label)
{
return (!LABEL_PRESERVE_P (label)
/* User declared labels must be preserved. */
&& LABEL_NAME (label) == 0
- && !in_expr_list_p (forced_labels, label));
+ && !in_insn_list_p (forced_labels, label));
}
/* 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;
/* Some labels can't be directly removed from the INSN chain, as they
might be references via variables, constant pool etc.
Convert them to the special NOTE_INSN_DELETED_LABEL note. */
- if (! can_delete_label_p (insn))
+ if (! can_delete_label_p (as_a <rtx_code_label *> (insn)))
{
const char *name = LABEL_NAME (insn);
basic_block bb = BLOCK_FOR_INSN (insn);
- rtx bb_note = NEXT_INSN (insn);
+ rtx_insn *bb_note = NEXT_INSN (insn);
really_delete = false;
PUT_CODE (insn, NOTE);
&& 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;
void
delete_insn_chain (rtx start, rtx finish, bool clear_bb)
{
- rtx prev, current;
+ rtx_insn *prev, *current;
/* Unchain the insns one by one. It would be quicker to delete all of these
with a single unchaining, rather than one at a time, but we need to keep
the NOTE's. */
- current = finish;
+ current = safe_as_a <rtx_insn *> (finish);
while (1)
{
prev = PREV_INSN (current);
- if (NOTE_P (current) && !can_delete_note_p (current))
+ if (NOTE_P (current) && !can_delete_note_p (as_a <rtx_note *> (current)))
;
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. */
static void
rtl_delete_block (basic_block b)
{
- rtx insn, end;
+ rtx_insn *insn, *end;
/* If the head of this block is a CODE_LABEL, then it might be the
label for an exception handler which can't be reached. We need
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);
FOR_EACH_BB_FN (bb, cfun)
{
- rtx end = BB_END (bb);
- rtx insn;
+ rtx_insn *end = BB_END (bb);
+ rtx_insn *insn;
for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
{
unsigned int
free_bb_for_insn (void)
{
- rtx insn;
+ rtx_insn *insn;
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (!BARRIER_P (insn))
BLOCK_FOR_INSN (insn) = NULL;
(i.e. both BEGIN and END will be updated. */
static void
-update_bb_for_insn_chain (rtx begin, rtx end, basic_block bb)
+update_bb_for_insn_chain (rtx_insn *begin, rtx_insn *end, basic_block bb)
{
- rtx insn;
+ rtx_insn *insn;
end = NEXT_INSN (end);
for (insn = begin; insn != end; insn = NEXT_INSN (insn))
even after reload. */
static bool
-flow_active_insn_p (const_rtx insn)
+flow_active_insn_p (const rtx_insn *insn)
{
if (active_insn_p (insn))
return true;
bool
contains_no_active_insn_p (const_basic_block bb)
{
- rtx insn;
+ rtx_insn *insn;
if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun) || bb == ENTRY_BLOCK_PTR_FOR_FN (cfun)
|| !single_succ_p (bb))
bool
can_fallthru (basic_block src, basic_block target)
{
- rtx insn = BB_END (src);
- rtx insn2;
+ rtx_insn *insn = BB_END (src);
+ rtx_insn *insn2;
edge e;
edge_iterator ei;
rtx_note *
bb_note (basic_block bb)
{
- rtx note;
+ rtx_insn *note;
note = BB_HEAD (bb);
if (LABEL_P (note))
/* Return the INSN immediately following the NOTE_INSN_BASIC_BLOCK
note associated with the BLOCK. */
-static rtx
+static rtx_insn *
first_insn_after_basic_block_note (basic_block block)
{
- rtx insn;
+ rtx_insn *insn;
/* Get the first instruction in the block. */
insn = BB_HEAD (block);
if (insn == NULL_RTX)
- return NULL_RTX;
+ return NULL;
if (LABEL_P (insn))
insn = NEXT_INSN (insn);
gcc_assert (NOTE_INSN_BASIC_BLOCK_P (insn));
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)
{
basic_block new_bb;
- rtx insn = (rtx) insnp;
+ rtx_insn *insn = (rtx_insn *) insnp;
edge e;
edge_iterator ei;
if (insn)
{
- rtx next = insn;
+ rtx_insn *next = insn;
insn = PREV_INSN (insn);
/* 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;
unique_locus_on_edge_between_p (basic_block a, basic_block b)
{
const location_t goto_locus = EDGE_SUCC (a, 0)->goto_locus;
- rtx insn, end;
+ rtx_insn *insn, *end;
if (LOCATION_LOCUS (goto_locus) == UNKNOWN_LOCATION)
return false;
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;
}
static void
rtl_merge_blocks (basic_block a, basic_block b)
{
- 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;
+ rtx_insn *b_head = BB_HEAD (b), *b_end = BB_END (b), *a_end = BB_END (a);
+ rtx_insn *del_first = NULL, *del_last = NULL;
+ rtx_insn *b_debug_start = b_end, *b_debug_end = b_end;
bool forwarder_p = (b->flags & BB_FORWARDER_BLOCK) != 0;
int b_empty = 0;
/* If there was a jump out of A, delete it. */
if (JUMP_P (a_end))
{
- rtx prev;
+ rtx_insn *prev;
for (prev = PREV_INSN (a_end); ; prev = PREV_INSN (prev))
if (!NOTE_P (prev)
del_first = a_end;
-#ifdef HAVE_cc0
/* If this was a conditional jump, we need to also delete
the insn that set cc0. */
- if (only_sets_cc0_p (prev))
+ if (HAVE_cc0 && only_sets_cc0_p (prev))
{
- rtx tmp = prev;
+ rtx_insn *tmp = prev;
prev = prev_nonnote_insn (prev);
if (!prev)
prev = BB_HEAD (a);
del_first = tmp;
}
-#endif
a_end = PREV_INSN (del_first);
}
/* 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);
/* Return the label in the head of basic block BLOCK. Create one if it doesn't
exist. */
-rtx
+rtx_code_label *
block_label (basic_block block)
{
if (block == EXIT_BLOCK_PTR_FOR_FN (cfun))
- return NULL_RTX;
+ return NULL;
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);
+ return as_a <rtx_code_label *> (BB_HEAD (block));
}
/* Attempt to perform edge redirection by replacing possibly complex jump
try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
{
basic_block src = e->src;
- rtx insn = BB_END (src), kill_from;
+ rtx_insn *insn = BB_END (src), *kill_from;
rtx set;
int fallthru = 0;
/* In case we zap a conditional jump, we'll need to kill
the cc0 setter too. */
kill_from = insn;
-#ifdef HAVE_cc0
- if (reg_mentioned_p (cc0_rtx, PATTERN (insn))
+ if (HAVE_cc0 && reg_mentioned_p (cc0_rtx, PATTERN (insn))
&& only_sets_cc0_p (PREV_INSN (insn)))
kill_from = PREV_INSN (insn);
-#endif
/* See if we can create the fallthru edge. */
if (in_cfglayout || can_fallthru (src, target))
/* Selectively unlink whole insn chain. */
if (in_cfglayout)
{
- rtx insn = BB_FOOTER (src);
+ rtx_insn *insn = BB_FOOTER (src);
delete_insn_chain (kill_from, BB_END (src), false);
if (PREV_INSN (insn))
SET_NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
else
- SET_BB_FOOTER (src) = NEXT_INSN (insn);
+ BB_FOOTER (src) = NEXT_INSN (insn);
if (NEXT_INSN (insn))
SET_PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
}
if (dump_file)
fprintf (dump_file, "Redirecting jump %i from %i to %i.\n",
INSN_UID (insn), e->dest->index, target->index);
- if (!redirect_jump (insn, block_label (target), 0))
+ if (!redirect_jump (as_a <rtx_jump_insn *> (insn),
+ block_label (target), 0))
{
gcc_assert (target == EXIT_BLOCK_PTR_FOR_FN (cfun));
return NULL;
/* Or replace possibly complicated jump insn by simple jump insn. */
else
{
- rtx target_label = block_label (target);
- rtx barrier, label;
+ rtx_code_label *target_label = block_label (target);
+ rtx_insn *barrier;
+ rtx label;
rtx_jump_table_data *table;
emit_jump_insn_after_noloc (gen_jump (target_label), insn);
/* Move the jump before barrier so that the notes
which originally were or were created before jump table are
inside the basic block. */
- rtx new_insn = BB_END (src);
+ rtx_insn *new_insn = BB_END (src);
update_bb_for_insn_chain (NEXT_INSN (BB_END (src)),
PREV_INSN (barrier), src);
doesn't work. */
static bool
-patch_jump_insn (rtx insn, rtx old_label, basic_block new_bb)
+patch_jump_insn (rtx_insn *insn, rtx_insn *old_label, basic_block new_bb)
{
rtx_jump_table_data *table;
rtx tmp;
{
rtvec vec;
int j;
- rtx new_label = block_label (new_bb);
+ rtx_code_label *new_label = block_label (new_bb);
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);
else if ((tmp = extract_asm_operands (PATTERN (insn))) != NULL)
{
int i, n = ASM_OPERANDS_LABEL_LENGTH (tmp);
- rtx new_label, note;
+ rtx note;
if (new_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
return false;
- new_label = block_label (new_bb);
+ rtx_code_label *new_label = block_label (new_bb);
for (i = 0; i < n; ++i)
{
/* 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))
+ if (!redirect_jump (as_a <rtx_jump_insn *> (insn),
+ block_label (new_bb), 0))
{
gcc_assert (new_bb == EXIT_BLOCK_PTR_FOR_FN (cfun));
return false;
static edge
redirect_branch_edge (edge e, basic_block target)
{
- rtx old_label = BB_HEAD (e->dest);
+ rtx_insn *old_label = BB_HEAD (e->dest);
basic_block src = e->src;
- rtx insn = BB_END (src);
+ rtx_insn *insn = BB_END (src);
/* We can only redirect non-fallthru edges of jump insn. */
if (e->flags & EDGE_FALLTHRU)
if (!currently_expanding_to_rtl)
{
- if (!patch_jump_insn (insn, old_label, target))
+ if (!patch_jump_insn (as_a <rtx_jump_insn *> (insn), old_label, target))
return NULL;
}
else
jumps (i.e. not yet split by find_many_sub_basic_blocks).
Redirect all of those that match our label. */
FOR_BB_INSNS (src, insn)
- if (JUMP_P (insn) && !patch_jump_insn (insn, old_label, target))
+ if (JUMP_P (insn) && !patch_jump_insn (as_a <rtx_jump_insn *> (insn),
+ old_label, target))
return NULL;
if (dump_file)
gcc_assert (current_ir_type () == IR_RTL_CFGRTL
|| current_ir_type () == IR_RTL_CFGLAYOUT);
if (current_ir_type () == IR_RTL_CFGLAYOUT)
- SET_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
edge b = unchecked_make_edge (e->src, target, 0);
bool redirected;
- redirected = redirect_jump (BB_END (e->src), block_label (target), 0);
+ redirected = redirect_jump (as_a <rtx_jump_insn *> (BB_END (e->src)),
+ block_label (target), 0);
gcc_assert (redirected);
note = find_reg_note (BB_END (e->src), REG_BR_PROB, NULL_RTX);
}
if (adjust_jump_target)
{
- rtx insn = BB_END (e->src), note;
- rtx old_label = BB_HEAD (e->dest);
- rtx new_label = BB_HEAD (target);
+ rtx_insn *insn = BB_END (e->src);
+ rtx note;
+ rtx_insn *old_label = BB_HEAD (e->dest);
+ rtx_insn *new_label = BB_HEAD (target);
if (JUMP_LABEL (insn) == old_label)
{
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);
if (target == EXIT_BLOCK_PTR_FOR_FN (cfun))
{
if (jump_label == ret_rtx)
- {
-#ifdef HAVE_return
- emit_jump_insn_after_setloc (gen_return (), BB_END (jump_block), loc);
-#else
- gcc_unreachable ();
-#endif
- }
+ emit_jump_insn_after_setloc (targetm.gen_return (),
+ BB_END (jump_block), loc);
else
{
gcc_assert (jump_label == simple_return_rtx);
-#ifdef HAVE_simple_return
- emit_jump_insn_after_setloc (gen_simple_return (),
+ emit_jump_insn_after_setloc (targetm.gen_simple_return (),
BB_END (jump_block), loc);
-#else
- gcc_unreachable ();
-#endif
}
set_return_jump_label (BB_END (jump_block));
}
else
{
- rtx label = block_label (target);
+ rtx_code_label *label = block_label (target);
emit_jump_insn_after_setloc (gen_jump (label), BB_END (jump_block), loc);
JUMP_LABEL (BB_END (jump_block)) = label;
LABEL_NUSES (label)++;
static void
rtl_tidy_fallthru_edge (edge e)
{
- rtx q;
+ rtx_insn *q;
basic_block b = e->src, c = b->next_bb;
/* ??? In a late-running flow pass, other folks may have deleted basic
&& (any_uncondjump_p (q)
|| single_succ_p (b)))
{
-#ifdef HAVE_cc0
+ rtx label;
+ rtx_jump_table_data *table;
+
+ if (tablejump_p (q, &label, &table))
+ {
+ /* The label is likely mentioned in some instruction before
+ the tablejump and might not be DCEd, so turn it into
+ a note instead and move before the tablejump that is going to
+ be deleted. */
+ const char *name = LABEL_NAME (label);
+ PUT_CODE (label, NOTE);
+ NOTE_KIND (label) = NOTE_INSN_DELETED_LABEL;
+ NOTE_DELETED_LABEL_NAME (label) = name;
+ rtx_insn *lab = safe_as_a <rtx_insn *> (label);
+ reorder_insns (lab, lab, PREV_INSN (q));
+ delete_insn (table);
+ }
+
/* If this was a conditional jump, we need to also delete
the insn that set cc0. */
- if (any_condjump_p (q) && only_sets_cc0_p (PREV_INSN (q)))
+ if (HAVE_cc0 && any_condjump_p (q) && only_sets_cc0_p (PREV_INSN (q)))
q = PREV_INSN (q);
-#endif
q = PREV_INSN (q);
}
rtl_split_edge (edge edge_in)
{
basic_block bb, new_bb;
- rtx before;
+ rtx_insn *before;
/* Abnormal edges cannot be split. */
gcc_assert (!(edge_in->flags & EDGE_ABNORMAL));
if (edge_in->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
before = BB_HEAD (edge_in->dest);
else
- before = NULL_RTX;
+ before = NULL;
/* If this is a fall through edge to the exit block, the blocks might be
not adjacent, and the right place is after the source. */
&& (edge_in->flags & EDGE_CROSSING))
{
after = last_bb_in_partition (edge_in->src);
- before = NEXT_INSN (BB_END (after));
+ before = get_last_bb_insn (after);
/* The instruction following the last bb in partition should
be a barrier, since it cannot end in a fall-through. */
gcc_checking_assert (BARRIER_P (before));
/* For asm goto even splitting of fallthru edge might
need insn patching, as other labels might point to the
old label. */
- rtx last = BB_END (edge_in->src);
+ rtx_insn *last = BB_END (edge_in->src);
if (last
&& JUMP_P (last)
&& edge_in->dest != EXIT_BLOCK_PTR_FOR_FN (cfun)
void
commit_one_edge_insertion (edge e)
{
- rtx before = NULL_RTX, after = NULL_RTX, insns, tmp, last;
+ rtx_insn *before = NULL, *after = NULL, *insns, *tmp, *last;
basic_block bb;
/* Pull the insns off the edge now since the edge might go away. */
insns = e->insns.r;
- e->insns.r = NULL_RTX;
+ e->insns.r = NULL;
/* Figure out where to put these insns. If the destination has
one predecessor, insert there. Except for the exit block. */
static void
rtl_dump_bb (FILE *outf, basic_block bb, int indent, int flags)
{
- rtx insn;
- rtx last;
+ rtx_insn *insn;
+ rtx_insn *last;
char *s_indent;
s_indent = (char *) alloca ((size_t) indent + 1);
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
{
FOR_EACH_BB_REVERSE_FN (bb, cfun)
{
- rtx x;
+ rtx_insn *x;
start[INSN_UID (BB_HEAD (bb))] = bb;
end[INSN_UID (BB_END (bb))] = bb;
static int
rtl_verify_bb_insns (void)
{
- rtx x;
+ rtx_insn *x;
int err = 0;
basic_block bb;
/* Check the general integrity of the basic blocks. */
FOR_EACH_BB_REVERSE_FN (bb, cfun)
{
- rtx insn;
+ rtx_insn *insn;
if (!(bb->flags & BB_RTL))
{
{
basic_block bb;
int err = 0;
- rtx x;
- rtx last_head = get_last_insn ();
+ rtx_insn *x;
+ rtx_insn *last_head = get_last_insn ();
basic_block *bb_info;
const int max_uid = get_max_uid ();
FOR_EACH_BB_REVERSE_FN (bb, cfun)
{
- rtx head = BB_HEAD (bb);
- rtx end = BB_END (bb);
+ rtx_insn *head = BB_HEAD (bb);
+ rtx_insn *end = BB_END (bb);
for (x = last_head; x != NULL_RTX; x = PREV_INSN (x))
{
e = find_fallthru_edge (bb->succs);
if (!e)
{
- rtx insn;
+ rtx_insn *insn;
/* Ensure existence of barrier in BB with no fallthru edges. */
for (insn = NEXT_INSN (BB_END (bb)); ; insn = NEXT_INSN (insn))
else if (e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun)
&& e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
{
- rtx insn;
+ rtx_insn *insn;
if (e->src->next_bb != e->dest)
{
{
basic_block bb;
int err = 0;
- rtx x;
+ rtx_insn *x;
int num_bb_notes;
- const rtx rtx_first = get_insns ();
+ rtx_insn * const rtx_first = get_insns ();
basic_block last_bb_seen = ENTRY_BLOCK_PTR_FOR_FN (cfun), curr_bb = NULL;
num_bb_notes = 0;
purge_dead_edges (basic_block bb)
{
edge e;
- rtx insn = BB_END (bb), note;
+ rtx_insn *insn = BB_END (bb);
+ rtx note;
bool purged = false;
bool found;
edge_iterator ei;
if (e && !CALL_P (BB_END (bb)) && !can_throw_internal (BB_END (bb)))
{
- rtx insn;
+ rtx_insn *insn;
/* Get past the new insns generated. Allow notes, as the insns
may be already deleted. */
if (CALL_P (insn) || can_throw_internal (insn))
{
- rtx stop, next;
+ rtx_insn *stop, *next;
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
associated with BB (e.g., barriers). If there are any such insns,
we return the last one. Otherwise, we return the end of BB. */
-static rtx
+static rtx_insn *
skip_insns_after_block (basic_block bb)
{
- rtx insn, last_insn, next_head, prev;
+ rtx_insn *insn, *last_insn, *next_head, *prev;
- next_head = NULL_RTX;
+ next_head = NULL;
if (bb->next_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
next_head = BB_HEAD (bb->next_bb);
/* Locate or create a label for a given basic block. */
-static rtx
+static rtx_insn *
label_for_bb (basic_block bb)
{
- rtx label = BB_HEAD (bb);
+ rtx_insn *label = BB_HEAD (bb);
if (!LABEL_P (label))
{
static void
record_effective_endpoints (void)
{
- rtx next_insn;
+ rtx_insn *next_insn;
basic_block bb;
- rtx insn;
+ rtx_insn *insn;
for (insn = get_insns ();
insn
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 end;
+ 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)
- SET_BB_FOOTER (bb) = unlink_insn_chain (NEXT_INSN (BB_END (bb)), end);
+ BB_FOOTER (bb) = unlink_insn_chain (NEXT_INSN (BB_END (bb)), end);
next_insn = NEXT_INSN (BB_END (bb));
}
{
bb->aux = NULL;
if (!stay_in_cfglayout_mode)
- SET_BB_HEADER (bb) = SET_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)
{
bb->aux)
{
edge e_fall, e_taken, e;
- rtx bb_end_insn;
+ rtx_insn *bb_end_insn;
rtx ret_label = NULL_RTX;
basic_block nb;
edge_iterator ei;
e_taken = e;
bb_end_insn = BB_END (bb);
- if (JUMP_P (bb_end_insn))
+ if (rtx_jump_insn *bb_end_jump = dyn_cast <rtx_jump_insn *> (bb_end_insn))
{
- ret_label = JUMP_LABEL (bb_end_insn);
- if (any_condjump_p (bb_end_insn))
+ ret_label = JUMP_LABEL (bb_end_jump);
+ if (any_condjump_p (bb_end_jump))
{
/* This might happen if the conditional jump has side
effects and could therefore not be optimized away.
to prevent rtl_verify_flow_info from complaining. */
if (!e_fall)
{
- gcc_assert (!onlyjump_p (bb_end_insn)
- || returnjump_p (bb_end_insn)
+ gcc_assert (!onlyjump_p (bb_end_jump)
+ || returnjump_p (bb_end_jump)
|| (e_taken->flags & EDGE_CROSSING));
- emit_barrier_after (bb_end_insn);
+ emit_barrier_after (bb_end_jump);
continue;
}
edge based on known or assumed probability. */
else if (bb->aux != e_taken->dest)
{
- rtx note = find_reg_note (bb_end_insn, REG_BR_PROB, 0);
+ rtx note = find_reg_note (bb_end_jump, REG_BR_PROB, 0);
if (note
&& XINT (note, 0) < REG_BR_PROB_BASE / 2
- && invert_jump (bb_end_insn,
+ && invert_jump (bb_end_jump,
(e_fall->dest
== EXIT_BLOCK_PTR_FOR_FN (cfun)
? NULL_RTX
/* Otherwise we can try to invert the jump. This will
basically never fail, however, keep up the pretense. */
- else if (invert_jump (bb_end_insn,
+ else if (invert_jump (bb_end_jump,
(e_fall->dest
== EXIT_BLOCK_PTR_FOR_FN (cfun)
? NULL_RTX
edge e2;
edge_iterator ei2;
basic_block dest, nb;
- rtx end;
+ rtx_insn *end;
insn = BB_END (e->src);
end = PREV_INSN (BB_HEAD (e->src));
}
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;
DEBUG_FUNCTION void
verify_insn_chain (void)
{
- rtx x, prevx, nextx;
+ rtx_insn *x, *prevx, *nextx;
int insn_cnt1, insn_cnt2;
for (prevx = NULL, insn_cnt1 = 1, x = get_insns ();
edge, we have to split that block. */
if (c == bb)
{
- bb = split_block (bb, NULL)->dest;
+ bb = split_block_after_labels (bb)->dest;
bb->aux = c->aux;
c->aux = bb;
- SET_BB_FOOTER (bb) = BB_FOOTER (c);
- SET_BB_FOOTER (c) = NULL;
+ BB_FOOTER (bb) = BB_FOOTER (c);
+ BB_FOOTER (c) = NULL;
}
while (c->aux != bb)
/* Do not duplicate blocks containing insns that can't be copied. */
if (targetm.cannot_copy_insn_p)
{
- rtx insn = BB_HEAD (bb);
+ rtx_insn *insn = BB_HEAD (bb);
while (1)
{
if (INSN_P (insn) && targetm.cannot_copy_insn_p (insn))
}
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
break;
case NOTE_INSN_EPILOGUE_BEG:
+ case NOTE_INSN_UPDATE_SJLJ_CONTEXT:
emit_note_copy (as_a <rtx_note *> (insn));
break;
}
insn = NEXT_INSN (last);
delete_insn (last);
- return safe_as_a <rtx_insn *> (insn);
+ return insn;
}
/* Create a duplicate of the basic block BB. */
static basic_block
cfg_layout_duplicate_bb (basic_block bb)
{
- rtx insn;
+ rtx_insn *insn;
basic_block new_bb;
insn = duplicate_insn_chain (BB_HEAD (bb), BB_END (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))
insn = NEXT_INSN (insn);
insn = duplicate_insn_chain (BB_FOOTER (bb), insn);
if (insn)
- SET_BB_FOOTER (new_bb) = unlink_insn_chain (insn, get_last_insn ());
+ BB_FOOTER (new_bb) = unlink_insn_chain (insn, get_last_insn ());
}
return new_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;
}
#endif
force_one_exit_fallthru ();
rtl_register_cfg_hooks ();
- if (reload_completed
-#ifdef HAVE_epilogue
- && !HAVE_epilogue
-#endif
- )
+ if (reload_completed && !HAVE_epilogue)
fixup_fallthru_exit_predecessor ();
fixup_reorder_chain ();
rtx insn = (rtx) insnp;
basic_block new_bb = rtl_split_block (bb, insn);
- SET_BB_FOOTER (new_bb) = BB_FOOTER (bb);
- SET_BB_FOOTER (bb) = NULL;
+ BB_FOOTER (new_bb) = BB_FOOTER (bb);
+ BB_FOOTER (bb) = NULL;
return new_bb;
}
static void
cfg_layout_delete_block (basic_block bb)
{
- rtx insn, next, prev = PREV_INSN (BB_HEAD (bb)), *to, remaints;
+ rtx_insn *insn, *next, *prev = PREV_INSN (BB_HEAD (bb)), *remaints;
+ rtx_insn **to;
if (BB_HEADER (bb))
{
if (PREV_INSN (insn))
SET_NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
else
- SET_BB_FOOTER (bb) = NEXT_INSN (insn);
+ BB_FOOTER (bb) = NEXT_INSN (insn);
if (NEXT_INSN (insn))
SET_PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
}
}
}
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;
cfg_layout_merge_blocks (basic_block a, basic_block b)
{
bool forwarder_p = (b->flags & BB_FORWARDER_BLOCK) != 0;
- rtx insn;
+ rtx_insn *insn;
gcc_checking_assert (cfg_layout_can_merge_blocks_p (a, b));
if (BB_FOOTER (b))
{
if (!BB_FOOTER (a))
- SET_BB_FOOTER (a) = SET_BB_FOOTER (b);
+ BB_FOOTER (a) = BB_FOOTER (b);
else
{
- rtx last = BB_FOOTER (a);
+ rtx_insn *last = BB_FOOTER (a);
while (NEXT_INSN (last))
last = NEXT_INSN (last);
SET_NEXT_INSN (last) = BB_FOOTER (b);
SET_PREV_INSN (BB_FOOTER (b)) = last;
}
- SET_BB_FOOTER (b) = NULL;
+ BB_FOOTER (b) = NULL;
}
/* Move things from b->header before a->footer.
if (BB_HEADER (b))
{
if (! BB_FOOTER (a))
- SET_BB_FOOTER (a) = BB_HEADER (b);
+ BB_FOOTER (a) = BB_HEADER (b);
else
{
- rtx last = BB_HEADER (b);
+ rtx_insn *last = BB_HEADER (b);
while (NEXT_INSN (last))
last = NEXT_INSN (last);
SET_NEXT_INSN (last) = BB_FOOTER (a);
SET_PREV_INSN (BB_FOOTER (a)) = last;
- SET_BB_FOOTER (a) = BB_HEADER (b);
+ 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);
static bool
rtl_block_empty_p (basic_block bb)
{
- rtx insn;
+ rtx_insn *insn;
if (bb == ENTRY_BLOCK_PTR_FOR_FN (cfun)
|| bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
static basic_block
rtl_split_block_before_cond_jump (basic_block bb)
{
- rtx insn;
- rtx split_point = NULL;
- rtx last = NULL;
+ rtx_insn *insn;
+ rtx_insn *split_point = NULL;
+ rtx_insn *last = NULL;
bool found_code = false;
FOR_BB_INSNS (bb, insn)
static bool
rtl_block_ends_with_call_p (basic_block bb)
{
- rtx insn = BB_END (bb);
+ rtx_insn *insn = BB_END (bb);
while (!CALL_P (insn)
&& insn != BB_HEAD (bb)
Helper function for rtl_flow_call_edges_add. */
static bool
-need_fake_edge_p (const_rtx insn)
+need_fake_edge_p (const rtx_insn *insn)
{
if (!INSN_P (insn))
return false;
if (check_last_block)
{
basic_block bb = EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb;
- rtx insn = BB_END (bb);
+ rtx_insn *insn = BB_END (bb);
/* Back up past insns that must be kept in the same block as a call. */
while (insn != BB_HEAD (bb)
for (i = NUM_FIXED_BLOCKS; i < last_bb; i++)
{
basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i);
- rtx insn;
- rtx prev_insn;
+ rtx_insn *insn;
+ rtx_insn *prev_insn;
if (!bb)
continue;
if (need_fake_edge_p (insn))
{
edge e;
- rtx split_at_insn = insn;
+ rtx_insn *split_at_insn = insn;
/* Don't split the block between a call and an insn that should
remain in the same block as the call. */
basic_block second_head ATTRIBUTE_UNUSED,
basic_block cond_bb, void *comp_rtx)
{
- rtx label, seq, jump;
+ rtx_code_label *label;
+ rtx_insn *seq, *jump;
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);
start_sequence ();
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, -1);
+ do_compare_rtx_and_jump (op0, op1, comp, 0, mode, NULL_RTX, NULL, label, -1);
jump = get_last_insn ();
JUMP_LABEL (jump) = label;
LABEL_NUSES (label)++;
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));
}
{
const_basic_block src = e->src;
const_basic_block target = EDGE_SUCC (src, EDGE_SUCC (src, 0) == e)->dest;
- const_rtx insn = BB_END (src), set;
+ const rtx_insn *insn = BB_END (src);
+ rtx set;
/* The conditions are taken from try_redirect_by_replacing_jump. */
if (target == EXIT_BLOCK_PTR_FOR_FN (cfun))
rtl_account_profile_record (basic_block bb, int after_pass,
struct profile_record *record)
{
- rtx insn;
+ rtx_insn *insn;
FOR_BB_INSNS (bb, insn)
if (INSN_P (insn))
{
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_;
-}
-
-/* BB_FOOTER as an rvalue. */
-
-rtx_insn *BB_FOOTER (const_basic_block bb)
-{
- rtx insn = bb->il.x.rtl->footer_;
- return safe_as_a <rtx_insn *> (insn);
-}
-
-/* BB_FOOTER as an lvalue. */
-
-rtx& SET_BB_FOOTER (basic_block bb)
-{
- return bb->il.x.rtl->footer_;
-}
-
#include "gt-cfgrtl.h"