/* The tracer pass for the GNU compiler.
Contributed by Jan Hubicka, SuSE Labs.
- Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
This file is part of GCC.
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 pass performs the tail duplication needed for superblock formation.
For more information see:
#include "timevar.h"
#include "params.h"
#include "coverage.h"
+#include "tree-pass.h"
static int count_insns (basic_block);
static bool ignore_bb_p (basic_block);
/* Return true if BB has been seen - it is connected to some trace
already. */
-#define seen(bb) (bb->rbi->visited || bb->rbi->next)
+#define seen(bb) (bb->il.rtl->visited || bb->aux)
/* Return true if we should ignore the basic block for purposes of tracing. */
static bool
ignore_bb_p (basic_block bb)
{
- if (bb->index < 0)
+ if (bb->index < NUM_FIXED_BLOCKS)
return true;
if (!maybe_hot_bb_p (bb))
return true;
static void
tail_duplicate (void)
{
- fibnode_t *blocks = xcalloc (last_basic_block, sizeof (fibnode_t));
- basic_block *trace = xmalloc (sizeof (basic_block) * n_basic_blocks);
- int *counts = xmalloc (sizeof (int) * last_basic_block);
+ fibnode_t *blocks = XCNEWVEC (fibnode_t, last_basic_block);
+ basic_block *trace = XNEWVEC (basic_block, n_basic_blocks);
+ int *counts = XNEWVEC (int, last_basic_block);
int ninsns = 0, nduplicated = 0;
gcov_type weighted_insns = 0, traced_insns = 0;
fibheap_t heap = fibheap_new ();
e = find_edge (bb, bb2);
nduplicated += counts [bb2->index];
- bb2 = duplicate_block (bb2, e);
+ bb2 = duplicate_block (bb2, e, bb);
/* Reconsider the original copy of block we've duplicated.
Removing the most common predecessor may make it to be
fprintf (dump_file, "Duplicated %i as %i [%i]\n",
old->index, bb2->index, bb2->frequency);
}
- bb->rbi->next = bb2;
- bb2->rbi->visited = 1;
+ bb->aux = bb2;
+ bb2->il.rtl->visited = 1;
bb = bb2;
/* In case the trace became infrequent, stop duplicating. */
if (ignore_bb_p (bb))
{
edge_iterator ei;
edge e, best = NULL;
- while (end->rbi->next)
- end = end->rbi->next;
+ while (end->aux)
+ end = end->aux;
FOR_EACH_EDGE (e, ei, end->succs)
if (e->dest != EXIT_BLOCK_PTR
&& e->dest != single_succ (ENTRY_BLOCK_PTR)
- && !e->dest->rbi->visited
+ && !e->dest->il.rtl->visited
&& (!best || EDGE_FREQUENCY (e) > EDGE_FREQUENCY (best)))
best = e;
if (best)
{
- end->rbi->next = best->dest;
- best->dest->rbi->visited = 1;
+ end->aux = best->dest;
+ best->dest->il.rtl->visited = 1;
}
else
for (; bb != EXIT_BLOCK_PTR; bb = bb->next_bb)
{
- if (!bb->rbi->visited)
+ if (!bb->il.rtl->visited)
{
- end->rbi->next = bb;
- bb->rbi->visited = 1;
+ end->aux = bb;
+ bb->il.rtl->visited = 1;
break;
}
}
}
}
-/* Main entry point to this file. FLAGS is the set of flags to pass
- to cfg_layout_initialize(). */
+/* Main entry point to this file. */
void
-tracer (unsigned int flags)
+tracer (void)
{
- if (n_basic_blocks <= 1)
- return;
+ gcc_assert (current_ir_type () == IR_RTL_CFGLAYOUT);
- timevar_push (TV_TRACER);
+ if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1)
+ return;
- cfg_layout_initialize (flags);
mark_dfs_back_edges ();
if (dump_file)
- dump_flow_info (dump_file);
+ dump_flow_info (dump_file, dump_flags);
tail_duplicate ();
layout_superblocks ();
+ relink_block_chain (/*stay_in_cfglayout_mode=*/true);
+
if (dump_file)
- dump_flow_info (dump_file);
- cfg_layout_finalize ();
+ dump_flow_info (dump_file, dump_flags);
/* Merge basic blocks in duplicated traces. */
- cleanup_cfg (CLEANUP_EXPENSIVE);
+ cleanup_cfg (0);
+}
+\f
+static bool
+gate_handle_tracer (void)
+{
+ return (optimize > 0 && flag_tracer);
+}
- timevar_pop (TV_TRACER);
+/* Run tracer. */
+static unsigned int
+rest_of_handle_tracer (void)
+{
+ if (dump_file)
+ dump_flow_info (dump_file, dump_flags);
+ tracer ();
+ return 0;
}
+
+struct tree_opt_pass pass_tracer =
+{
+ "tracer", /* name */
+ gate_handle_tracer, /* gate */
+ rest_of_handle_tracer, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_TRACER, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func, /* todo_flags_finish */
+ 'T' /* letter */
+};
+