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. */
#include "config.h"
#include "system.h"
#include "ggc.h"
#include "alloc-pool.h"
#include "flags.h"
+#include "tree-pass.h"
+#include "vecprim.h"
/* Holds the interesting trailing notes for the function. */
rtx cfg_layout_function_footer, cfg_layout_function_header;
case NOTE:
switch (NOTE_LINE_NUMBER (insn))
{
- case NOTE_INSN_LOOP_END:
case NOTE_INSN_BLOCK_END:
last_insn = insn;
continue;
/* It is possible to hit contradictory sequence. For instance:
jump_insn
- NOTE_INSN_LOOP_BEG
+ NOTE_INSN_BLOCK_BEG
barrier
Where barrier belongs to jump_insn, but the note does not. This can be
created by removing the basic block originally following
- NOTE_INSN_LOOP_BEG. In such case reorder the notes. */
+ NOTE_INSN_BLOCK_BEG. In such case reorder the notes. */
for (insn = last_insn; insn != BB_END (bb); insn = prev)
{
if (NOTE_P (insn))
switch (NOTE_LINE_NUMBER (insn))
{
- case NOTE_INSN_LOOP_END:
case NOTE_INSN_BLOCK_END:
case NOTE_INSN_DELETED:
case NOTE_INSN_DELETED_LABEL:
rtx end;
if (PREV_INSN (BB_HEAD (bb)) && next_insn != BB_HEAD (bb))
- bb->rbi->header = unlink_insn_chain (next_insn,
+ bb->il.rtl->header = 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->rbi->footer = unlink_insn_chain (NEXT_INSN (BB_END (bb)), end);
+ bb->il.rtl->footer = unlink_insn_chain (NEXT_INSN (BB_END (bb)), end);
next_insn = NEXT_INSN (BB_END (bb));
}
cfg_layout_function_footer = unlink_insn_chain (cfg_layout_function_footer, get_last_insn ());
}
\f
-DEF_VEC_I(int);
-DEF_VEC_ALLOC_I(int,heap);
-
/* Data structures representing mapping of INSN_LOCATOR into scope blocks, line
numbers and files. In order to be GGC friendly we need to use separate
varrays. This also slightly improve the memory locality in binary search.
represented via INSN_NOTEs. Replace them by representation using
INSN_LOCATORs. */
-void
+unsigned int
insn_locators_initialize (void)
{
tree block = NULL;
set_block_levels (DECL_INITIAL (cfun->decl), 0);
free_block_changes ();
+ return 0;
}
+struct tree_opt_pass pass_insn_locators_initialize =
+{
+ "locators", /* name */
+ NULL, /* gate */
+ insn_locators_initialize, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ 0, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func, /* todo_flags_finish */
+ 0 /* letter */
+};
+
+
/* For each lexical block, set BLOCK_NUMBER to the depth at which it is
found in the block tree. */
/* First do the bulk reordering -- rechain the blocks without regard to
the needed changes to jumps and labels. */
- for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0;
+ for (bb = ENTRY_BLOCK_PTR->next_bb, index = NUM_FIXED_BLOCKS;
bb != 0;
- bb = bb->rbi->next, index++)
+ bb = bb->aux, index++)
{
- if (bb->rbi->header)
+ if (bb->il.rtl->header)
{
if (insn)
- NEXT_INSN (insn) = bb->rbi->header;
+ NEXT_INSN (insn) = bb->il.rtl->header;
else
- set_first_insn (bb->rbi->header);
- PREV_INSN (bb->rbi->header) = insn;
- insn = bb->rbi->header;
+ set_first_insn (bb->il.rtl->header);
+ PREV_INSN (bb->il.rtl->header) = insn;
+ insn = bb->il.rtl->header;
while (NEXT_INSN (insn))
insn = NEXT_INSN (insn);
}
set_first_insn (BB_HEAD (bb));
PREV_INSN (BB_HEAD (bb)) = insn;
insn = BB_END (bb);
- if (bb->rbi->footer)
+ if (bb->il.rtl->footer)
{
- 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);
}
/* Now add jumps and labels as needed to match the blocks new
outgoing edges. */
- for (bb = ENTRY_BLOCK_PTR->next_bb; bb ; bb = bb->rbi->next)
+ for (bb = ENTRY_BLOCK_PTR->next_bb; bb ; bb = bb->aux)
{
edge e_fall, e_taken, e;
rtx bb_end_insn;
if (any_condjump_p (bb_end_insn))
{
/* If the old fallthru is still next, nothing to do. */
- if (bb->rbi->next == e_fall->dest
+ if (bb->aux == e_fall->dest
|| e_fall->dest == EXIT_BLOCK_PTR)
continue;
/* The degenerated case of conditional jump jumping to the next
- instruction can happen on target having jumps with side
- effects.
-
- Create temporarily the duplicated edge representing branch.
- It will get unidentified by force_nonfallthru_and_redirect
- that would otherwise get confused by fallthru edge not pointing
- to the next basic block. */
+ instruction can happen for jumps with side effects. We need
+ to construct a forwarder block and this will be done just
+ fine by force_nonfallthru below. */
if (!e_taken)
- {
- rtx note;
- edge e_fake;
- bool redirected;
-
- e_fake = unchecked_make_edge (bb, e_fall->dest, 0);
-
- redirected = redirect_jump (BB_END (bb),
- block_label (bb), 0);
- gcc_assert (redirected);
-
- note = find_reg_note (BB_END (bb), REG_BR_PROB, NULL_RTX);
- if (note)
- {
- int prob = INTVAL (XEXP (note, 0));
-
- e_fake->probability = prob;
- e_fake->count = e_fall->count * prob / REG_BR_PROB_BASE;
- e_fall->probability -= e_fall->probability;
- e_fall->count -= e_fake->count;
- if (e_fall->probability < 0)
- e_fall->probability = 0;
- if (e_fall->count < 0)
- e_fall->count = 0;
- }
- }
- /* There is one special case: if *neither* block is next,
+ ;
+
+ /* There is another special case: if *neither* block is next,
such as happens at the very end of a function, then we'll
need to add a new unconditional jump. Choose the taken
edge based on known or assumed probability. */
- else if (bb->rbi->next != e_taken->dest)
+ else if (bb->aux != e_taken->dest)
{
rtx note = find_reg_note (bb_end_insn, REG_BR_PROB, 0);
continue;
/* If the fallthru block is still next, nothing to do. */
- if (bb->rbi->next == e_fall->dest)
+ if (bb->aux == e_fall->dest)
continue;
/* A fallthru to exit block. */
nb = force_nonfallthru (e_fall);
if (nb)
{
- initialize_bb_rbi (nb);
- nb->rbi->visited = 1;
- nb->rbi->next = bb->rbi->next;
- bb->rbi->next = nb;
+ nb->il.rtl->visited = 1;
+ nb->aux = bb->aux;
+ bb->aux = nb;
/* Don't process this new block. */
bb = nb;
if (dump_file)
{
fprintf (dump_file, "Reordered sequence:\n");
- for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0;
+ for (bb = ENTRY_BLOCK_PTR->next_bb, index = NUM_FIXED_BLOCKS;
bb;
- bb = bb->rbi->next, index++)
+ bb = bb->aux, index++)
{
fprintf (dump_file, " %i ", index);
if (get_bb_original (bb))
prev_bb = ENTRY_BLOCK_PTR;
bb = ENTRY_BLOCK_PTR->next_bb;
- index = 0;
+ index = NUM_FIXED_BLOCKS;
- for (; bb; prev_bb = bb, bb = bb->rbi->next, index ++)
+ for (; bb; prev_bb = bb, bb = bb->aux, index ++)
{
bb->index = index;
- BASIC_BLOCK (index) = bb;
+ SET_BASIC_BLOCK (index, bb);
bb->prev_bb = prev_bb;
prev_bb->next_bb = bb;
if (e->flags & EDGE_FALLTHRU)
bb = e->src;
- if (bb && bb->rbi->next)
+ if (bb && bb->aux)
{
basic_block c = ENTRY_BLOCK_PTR->next_bb;
if (c == bb)
{
bb = split_block (bb, NULL)->dest;
- initialize_bb_rbi (bb);
- bb->rbi->next = c->rbi->next;
- c->rbi->next = bb;
- bb->rbi->footer = c->rbi->footer;
- c->rbi->footer = NULL;
+ bb->aux = c->aux;
+ c->aux = bb;
+ bb->il.rtl->footer = c->il.rtl->footer;
+ c->il.rtl->footer = NULL;
}
- while (c->rbi->next != bb)
- c = c->rbi->next;
+ while (c->aux != bb)
+ c = c->aux;
- c->rbi->next = bb->rbi->next;
- while (c->rbi->next)
- c = c->rbi->next;
+ c->aux = bb->aux;
+ while (c->aux)
+ c = c->aux;
- c->rbi->next = bb;
- bb->rbi->next = NULL;
+ c->aux = bb;
+ bb->aux = NULL;
}
}
\f
in first BB, we may want to copy the block. */
case NOTE_INSN_PROLOGUE_END:
- case NOTE_INSN_LOOP_BEG:
- case NOTE_INSN_LOOP_END:
- /* Strip down the loop notes - we don't really want to keep
- them consistent in loop copies. */
case NOTE_INSN_DELETED:
case NOTE_INSN_DELETED_LABEL:
/* No problem to strip these. */
EXIT_BLOCK_PTR->prev_bb);
BB_COPY_PARTITION (new_bb, bb);
- if (bb->rbi->header)
+ if (bb->il.rtl->header)
{
- insn = bb->rbi->header;
+ insn = bb->il.rtl->header;
while (NEXT_INSN (insn))
insn = NEXT_INSN (insn);
- insn = duplicate_insn_chain (bb->rbi->header, insn);
+ insn = duplicate_insn_chain (bb->il.rtl->header, insn);
if (insn)
- new_bb->rbi->header = unlink_insn_chain (insn, get_last_insn ());
+ new_bb->il.rtl->header = unlink_insn_chain (insn, get_last_insn ());
}
- if (bb->rbi->footer)
+ if (bb->il.rtl->footer)
{
- insn = bb->rbi->footer;
+ insn = bb->il.rtl->footer;
while (NEXT_INSN (insn))
insn = NEXT_INSN (insn);
- insn = duplicate_insn_chain (bb->rbi->footer, insn);
+ insn = duplicate_insn_chain (bb->il.rtl->footer, insn);
if (insn)
- new_bb->rbi->footer = unlink_insn_chain (insn, get_last_insn ());
+ new_bb->il.rtl->footer = unlink_insn_chain (insn, get_last_insn ());
}
if (bb->il.rtl->global_live_at_start)
void
cfg_layout_initialize (unsigned int flags)
{
- basic_block bb;
-
- FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
- initialize_bb_rbi (bb);
-
initialize_original_copy_tables ();
cfg_layout_rtl_register_cfg_hooks ();
free (superblocks);
}
-/* Finalize the changes: reorder insn list according to the sequence, enter
- compensation code, rebuild scope forest. */
+/* Finalize the changes: reorder insn list according to the sequence specified
+ by aux pointers, enter compensation code, rebuild scope forest. */
void
cfg_layout_finalize (void)
verify_insn_chain ();
#endif
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
- bb->rbi = NULL;
+ {
+ bb->il.rtl->header = bb->il.rtl->footer = NULL;
+ bb->aux = NULL;
+ bb->il.rtl->visited = 0;
+ }
break_superblocks ();
is copied, we do not set the new blocks as header or latch.
Created copies of N_EDGES edges in array EDGES are stored in array NEW_EDGES,
- also in the same order. */
+ also in the same order.
+
+ Newly created basic blocks are put after the basic block AFTER in the
+ instruction stream, and the order of the blocks in BBS array is preserved. */
void
copy_bbs (basic_block *bbs, unsigned n, basic_block *new_bbs,
edge *edges, unsigned num_edges, edge *new_edges,
- struct loop *base)
+ struct loop *base, basic_block after)
{
unsigned i, j;
basic_block bb, new_bb, dom_bb;
{
/* Duplicate. */
bb = bbs[i];
- new_bb = new_bbs[i] = duplicate_block (bb, NULL);
+ new_bb = new_bbs[i] = duplicate_block (bb, NULL, after);
+ after = new_bb;
bb->flags |= BB_DUPLICATED;
/* Add to loop. */
add_bb_to_loop (new_bb, bb->loop_father->copy);