/* Basic block reordering routines for the GNU compiler.
- Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
This file is part of GCC.
#include "alloc-pool.h"
#include "flags.h"
#include "tree-pass.h"
+#include "df.h"
#include "vecprim.h"
/* Holds the interesting trailing notes for the function. */
static rtx label_for_bb (basic_block);
static void fixup_reorder_chain (void);
-static void set_block_levels (tree, int);
static void change_scope (rtx, tree, tree);
void verify_insn_chain (void);
continue;
case NOTE:
- switch (NOTE_LINE_NUMBER (insn))
+ switch (NOTE_KIND (insn))
{
case NOTE_INSN_BLOCK_END:
- last_insn = insn;
- continue;
- case NOTE_INSN_DELETED:
- case NOTE_INSN_DELETED_LABEL:
+ gcc_unreachable ();
continue;
-
default:
continue;
break;
{
prev = PREV_INSN (insn);
if (NOTE_P (insn))
- switch (NOTE_LINE_NUMBER (insn))
+ switch (NOTE_KIND (insn))
{
case NOTE_INSN_BLOCK_END:
+ gcc_unreachable ();
+ break;
case NOTE_INSN_DELETED:
case NOTE_INSN_DELETED_LABEL:
continue;
for (insn = get_insns ();
insn
&& NOTE_P (insn)
- && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK;
+ && NOTE_KIND (insn) != NOTE_INSN_BASIC_BLOCK;
insn = NEXT_INSN (insn))
continue;
/* No basic blocks at all? */
than the following one. Similarly for the other properties. */
static VEC(int,heap) *block_locators_locs;
static GTY(()) VEC(tree,gc) *block_locators_blocks;
-static VEC(int,heap) *line_locators_locs;
-static VEC(int,heap) *line_locators_lines;
-static VEC(int,heap) *file_locators_locs;
-static GTY(()) varray_type file_locators_files;
+static VEC(int,heap) *locations_locators_locs;
+DEF_VEC_O(location_t);
+DEF_VEC_ALLOC_O(location_t,heap);
+static VEC(location_t,heap) *locations_locators_vals;
int prologue_locator;
int epilogue_locator;
-/* During the RTL expansion the lexical blocks and line numbers are
- represented via INSN_NOTEs. Replace them by representation using
- INSN_LOCATORs. */
+/* Hold current location information and last location information, so the
+ datastructures are built lazily only when some instructions in given
+ place are needed. */
+location_t curr_location, last_location;
+static tree curr_block, last_block;
+static int curr_rtl_loc = -1;
-unsigned int
-insn_locators_initialize (void)
+/* Allocate insn locator datastructure. */
+void
+insn_locators_alloc (void)
{
- tree block = NULL;
- tree last_block = NULL;
- rtx insn, next;
- int loc = 0;
- int line_number = 0, last_line_number = 0;
- const char *file_name = NULL, *last_file_name = NULL;
-
prologue_locator = epilogue_locator = 0;
block_locators_locs = VEC_alloc (int, heap, 32);
block_locators_blocks = VEC_alloc (tree, gc, 32);
- line_locators_locs = VEC_alloc (int, heap, 32);
- line_locators_lines = VEC_alloc (int, heap, 32);
- file_locators_locs = VEC_alloc (int, heap, 32);
- VARRAY_CHAR_PTR_INIT (file_locators_files, 32, "file_locators_files");
-
- for (insn = get_insns (); insn; insn = next)
- {
- int active = 0;
-
- next = NEXT_INSN (insn);
-
- if (NOTE_P (insn))
- {
- gcc_assert (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_BEG
- && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_END);
- if (NOTE_LINE_NUMBER (insn) > 0)
- {
- expanded_location xloc;
- NOTE_EXPANDED_LOCATION (xloc, insn);
- line_number = xloc.line;
- file_name = xloc.file;
- delete_insn (insn);
- }
- }
- else
- active = (active_insn_p (insn)
- && GET_CODE (PATTERN (insn)) != ADDR_VEC
- && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC);
-
- check_block_change (insn, &block);
+ locations_locators_locs = VEC_alloc (int, heap, 32);
+ locations_locators_vals = VEC_alloc (location_t, heap, 32);
+
+#ifdef USE_MAPPED_LOCATION
+ last_location = -1;
+ curr_location = -1;
+#else
+ last_location.line = -1;
+ curr_location.line = -1;
+#endif
+ curr_block = NULL;
+ last_block = NULL;
+ curr_rtl_loc = 0;
+}
- if (active
- || !next
- || (!prologue_locator && file_name))
- {
- if (last_block != block)
- {
- loc++;
- VEC_safe_push (int, heap, block_locators_locs, loc);
- VEC_safe_push (tree, gc, block_locators_blocks, block);
- last_block = block;
- }
- if (last_line_number != line_number)
- {
- loc++;
- VEC_safe_push (int, heap, line_locators_locs, loc);
- VEC_safe_push (int, heap, line_locators_lines, line_number);
- last_line_number = line_number;
- }
- if (last_file_name != file_name)
- {
- loc++;
- VEC_safe_push (int, heap, file_locators_locs, loc);
- VARRAY_PUSH_CHAR_PTR (file_locators_files, (char *) file_name);
- last_file_name = file_name;
- }
- if (!prologue_locator && file_name)
- prologue_locator = loc;
- if (!next)
- epilogue_locator = loc;
- if (active)
- INSN_LOCATOR (insn) = loc;
- }
- }
+/* At the end of emit stage, clear current location. */
+void
+insn_locators_finalize (void)
+{
+ if (curr_rtl_loc >= 0)
+ epilogue_locator = curr_insn_locator ();
+ curr_rtl_loc = -1;
+}
- /* Tag the blocks with a depth number so that change_scope can find
- the common parent easily. */
- set_block_levels (DECL_INITIAL (cfun->decl), 0);
+/* Set current location. */
+void
+set_curr_insn_source_location (location_t location)
+{
+ /* IV opts calls into RTL expansion to compute costs of operations. At this
+ time locators are not initialized. */
+ if (curr_rtl_loc == -1)
+ return;
+#ifdef USE_MAPPED_LOCATION
+ if (location == last_location)
+ return;
+#else
+ if (location.file && last_location.file
+ && !strcmp (location.file, last_location.file)
+ && location.line == last_location.line)
+ return;
+#endif
+ curr_location = location;
+}
- free_block_changes ();
- return 0;
+/* Set current scope block. */
+void
+set_curr_insn_block (tree b)
+{
+ /* IV opts calls into RTL expansion to compute costs of operations. At this
+ time locators are not initialized. */
+ if (curr_rtl_loc == -1)
+ return;
+ if (b)
+ curr_block = b;
}
-struct tree_opt_pass pass_insn_locators_initialize =
+/* Return current insn locator. */
+int
+curr_insn_locator (void)
{
- "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 */
-};
+ if (curr_rtl_loc == -1)
+ return 0;
+ if (last_block != curr_block)
+ {
+ curr_rtl_loc++;
+ VEC_safe_push (int, heap, block_locators_locs, curr_rtl_loc);
+ VEC_safe_push (tree, gc, block_locators_blocks, curr_block);
+ last_block = curr_block;
+ }
+#ifdef USE_MAPPED_LOCATION
+ if (last_location != curr_location)
+#else
+ if (last_location.file != curr_location.file
+ || last_location.line != curr_location.line)
+#endif
+ {
+ curr_rtl_loc++;
+ VEC_safe_push (int, heap, locations_locators_locs, curr_rtl_loc);
+ VEC_safe_push (location_t, heap, locations_locators_vals, &curr_location);
+ last_location = curr_location;
+ }
+ return curr_rtl_loc;
+}
static unsigned int
into_cfg_layout_mode (void)
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. */
-
-static void
-set_block_levels (tree block, int level)
-{
- while (block)
- {
- BLOCK_NUMBER (block) = level;
- set_block_levels (BLOCK_SUBBLOCKS (block), level + 1);
- block = BLOCK_CHAIN (block);
- }
-}
\f
/* Return sope resulting from combination of S1 and S2. */
static tree
}
/* Return line number of the statement specified by the locator. */
-int
-locator_line (int loc)
+static location_t
+locator_location (int loc)
{
- int max = VEC_length (int, line_locators_locs);
+ int max = VEC_length (int, locations_locators_locs);
int min = 0;
- if (!max || !loc)
- return 0;
while (1)
{
int pos = (min + max) / 2;
- int tmp = VEC_index (int, line_locators_locs, pos);
+ int tmp = VEC_index (int, locations_locators_locs, pos);
if (tmp <= loc && min != pos)
min = pos;
break;
}
}
- return VEC_index (int, line_locators_lines, min);
+ return *VEC_index (location_t, locations_locators_vals, min);
+}
+
+/* Return source line of the statement that produced this insn. */
+int
+locator_line (int loc)
+{
+ expanded_location xloc;
+ if (!loc)
+ return 0;
+ else
+ xloc = expand_location (locator_location (loc));
+ return xloc.line;
}
/* Return line number of the statement that produced this insn. */
const char *
locator_file (int loc)
{
- int max = VEC_length (int, file_locators_locs);
- int min = 0;
-
- if (!max || !loc)
- return NULL;
- while (1)
- {
- int pos = (min + max) / 2;
- int tmp = VEC_index (int, file_locators_locs, pos);
-
- if (tmp <= loc && min != pos)
- min = pos;
- else if (tmp > loc && max != pos)
- max = pos;
- else
- {
- min = pos;
- break;
- }
- }
- return VARRAY_CHAR_PTR (file_locators_files, min);
+ expanded_location xloc;
+ if (!loc)
+ return 0;
+ else
+ xloc = expand_location (locator_location (loc));
+ return xloc.file;
}
/* Return source file of the statement that produced this insn. */
fprintf (dump_file, "Reordered sequence:\n");
for (bb = ENTRY_BLOCK_PTR->next_bb, index = NUM_FIXED_BLOCKS;
bb;
- bb = bb->aux, index++)
+ bb = (basic_block) bb->aux, index++)
{
fprintf (dump_file, " %i ", index);
if (get_bb_original (bb))
/* Now reorder the blocks. */
prev_bb = ENTRY_BLOCK_PTR;
bb = ENTRY_BLOCK_PTR->next_bb;
- for (; bb; prev_bb = bb, bb = bb->aux)
+ for (; bb; prev_bb = bb, bb = (basic_block) bb->aux)
{
bb->prev_bb = prev_bb;
prev_bb->next_bb = bb;
/* 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; bb; bb = bb->aux)
+ for (bb = ENTRY_BLOCK_PTR->next_bb; bb; bb = (basic_block) bb->aux)
{
if (bb->il.rtl->header)
{
/* Now add jumps and labels as needed to match the blocks new
outgoing edges. */
- for (bb = ENTRY_BLOCK_PTR->next_bb; bb ; bb = bb->aux)
+ for (bb = ENTRY_BLOCK_PTR->next_bb; bb ; bb = (basic_block) bb->aux)
{
edge e_fall, e_taken, e;
rtx bb_end_insn;
FOR_EACH_EDGE (e, ei, bb->succs)
if (e->flags & EDGE_FALLTHRU)
break;
-
+
if (e && !can_fallthru (e->src, e->dest))
force_nonfallthru (e);
}
}
while (c->aux != bb)
- c = c->aux;
+ c = (basic_block) c->aux;
c->aux = bb->aux;
while (c->aux)
- c = c->aux;
+ c = (basic_block) c->aux;
c->aux = bb;
bb->aux = NULL;
break;
case NOTE:
- switch (NOTE_LINE_NUMBER (insn))
+ switch (NOTE_KIND (insn))
{
/* In case prologue is empty and function contain label
in first BB, we may want to copy the block. */
default:
/* All other notes should have already been eliminated.
*/
- gcc_assert (NOTE_LINE_NUMBER (insn) >= 0);
-
- /* It is possible that no_line_number is set and the note
- won't be emitted. */
- emit_note_copy (insn);
+ gcc_unreachable ();
}
break;
default:
new_bb->il.rtl->footer = unlink_insn_chain (insn, get_last_insn ());
}
- if (bb->il.rtl->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,
- bb->il.rtl->global_live_at_start);
- COPY_REG_SET (new_bb->il.rtl->global_live_at_end,
- bb->il.rtl->global_live_at_end);
- }
-
return new_bb;
}
+
\f
/* Main entry point to this module - initialize the datastructures for
CFG layout changes. It keeps LOOPS up-to-date if not null.
- FLAGS is a set of additional flags to pass to cleanup_cfg(). It should
- include CLEANUP_UPDATE_LIFE if liveness information must be kept up
- to date. */
+ FLAGS is a set of additional flags to pass to cleanup_cfg(). */
void
cfg_layout_initialize (unsigned int flags)
{
+ rtx x;
+ basic_block bb;
+
initialize_original_copy_tables ();
cfg_layout_rtl_register_cfg_hooks ();
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))
+ {
+ bb = BLOCK_FOR_INSN (XEXP (x, 0));
+ bb->flags |= BB_NON_LOCAL_GOTO_TARGET;
+ }
+
cleanup_cfg (CLEANUP_CFGLAYOUT | flags);
}