/* Basic block reordering routines for the GNU compiler.
- Copyright (C) 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
+ the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful, but WITHOUT
License for more details.
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, 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
/* This (greedy) algorithm constructs traces in several rounds.
The construction starts from "seeds". The seed for the first round
#include "params.h"
#include "toplev.h"
#include "tree-pass.h"
+#include "df.h"
#ifndef HAVE_conditional_execution
#define HAVE_conditional_execution 0
static bool copy_bb_p (basic_block, int);
static int get_uncond_jump_length (void);
static bool push_to_next_round_p (basic_block, int, int, int, gcov_type);
-static void find_rarely_executed_basic_blocks_and_crossing_edges (edge *,
+static void find_rarely_executed_basic_blocks_and_crossing_edges (edge **,
int *,
int *);
static void add_labels_and_missing_jumps (edge *, int);
cache locality). */
static void
-find_rarely_executed_basic_blocks_and_crossing_edges (edge *crossing_edges,
+find_rarely_executed_basic_blocks_and_crossing_edges (edge **crossing_edges,
int *n_crossing_edges,
int *max_idx)
{
if (i == *max_idx)
{
*max_idx *= 2;
- crossing_edges = xrealloc (crossing_edges,
+ *crossing_edges = xrealloc (*crossing_edges,
(*max_idx) * sizeof (edge));
}
- crossing_edges[i++] = e;
+ (*crossing_edges)[i++] = e;
}
else
e->flags &= ~EDGE_CROSSING;
last_bb->aux = new_bb;
prev_bb = last_bb;
last_bb = new_bb;
-
- /* Update register liveness information. */
-
- 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_end,
- prev_bb->il.rtl->global_live_at_end);
- COPY_REG_SET (new_bb->il.rtl->global_live_at_start,
- prev_bb->il.rtl->global_live_at_end);
-
/* Put appropriate instructions in new bb. */
new_label = gen_label_rtx ();
well. */
if (!HAS_LONG_UNCOND_BRANCH)
- {
- fix_crossing_unconditional_branches ();
- reg_scan (get_insns(), max_reg_num ());
- }
+ fix_crossing_unconditional_branches ();
add_reg_crossing_jump_notes ();
}
the set of flags to pass to cfg_layout_initialize(). */
void
-reorder_basic_blocks (unsigned int flags)
+reorder_basic_blocks (void)
{
int n_traces;
int i;
struct trace *traces;
- if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1)
- return;
+ gcc_assert (current_ir_type () == IR_RTL_CFGLAYOUT);
- if (targetm.cannot_modify_jumps_p ())
+ if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1)
return;
- cfg_layout_initialize (flags);
-
set_edge_can_fallthru_flag ();
mark_dfs_back_edges ();
FREE (traces);
FREE (bbd);
+ relink_block_chain (/*stay_in_cfglayout_mode=*/true);
+
if (dump_file)
dump_flow_info (dump_file, dump_flags);
- cfg_layout_finalize ();
if (flag_reorder_blocks_and_partition)
verify_hot_cold_block_grouping ();
}
static bool
gate_duplicate_computed_gotos (void)
{
+ if (targetm.cannot_modify_jumps_p ())
+ return false;
return (optimize > 0 && flag_expensive_optimizations && !optimize_size);
}
if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1)
return 0;
- if (targetm.cannot_modify_jumps_p ())
- return 0;
-
cfg_layout_initialize (0);
/* We are estimating the length of uncond jump insn only once
&& cur_bb->next_bb->index >= NUM_FIXED_BLOCKS)
cur_bb->aux = cur_bb->next_bb;
- find_rarely_executed_basic_blocks_and_crossing_edges (crossing_edges,
+ find_rarely_executed_basic_blocks_and_crossing_edges (&crossing_edges,
&n_crossing_edges,
&max_edges);
free (crossing_edges);
- cfg_layout_finalize();
+ cfg_layout_finalize ();
}
\f
static bool
gate_handle_reorder_blocks (void)
{
+ if (targetm.cannot_modify_jumps_p ())
+ return false;
return (optimize > 0);
}
static unsigned int
rest_of_handle_reorder_blocks (void)
{
- bool changed;
- unsigned int liveness_flags;
+ basic_block bb;
/* Last attempt to optimize CFG, as scheduling, peepholing and insn
splitting possibly introduced more crossjumping opportunities. */
- liveness_flags = (!HAVE_conditional_execution ? CLEANUP_UPDATE_LIFE : 0);
- changed = cleanup_cfg (CLEANUP_EXPENSIVE | liveness_flags);
+ cfg_layout_initialize (CLEANUP_EXPENSIVE);
if (flag_sched2_use_traces && flag_schedule_insns_after_reload)
{
timevar_push (TV_TRACER);
- tracer (liveness_flags);
+ tracer ();
timevar_pop (TV_TRACER);
}
if (flag_reorder_blocks || flag_reorder_blocks_and_partition)
- reorder_basic_blocks (liveness_flags);
+ reorder_basic_blocks ();
if (flag_reorder_blocks || flag_reorder_blocks_and_partition
|| (flag_sched2_use_traces && flag_schedule_insns_after_reload))
- changed |= cleanup_cfg (CLEANUP_EXPENSIVE | liveness_flags);
+ cleanup_cfg (CLEANUP_EXPENSIVE);
- /* On conditional execution targets we can not update the life cheaply, so
- we deffer the updating to after both cleanups. This may lose some cases
- but should not be terribly bad. */
- if (changed && HAVE_conditional_execution)
- update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
- PROP_DEATH_NOTES);
+ FOR_EACH_BB (bb)
+ if (bb->next_bb != EXIT_BLOCK_PTR)
+ bb->aux = bb->next_bb;
+ cfg_layout_finalize ();
/* Add NOTE_INSN_SWITCH_TEXT_SECTIONS notes. */
insert_section_boundary_note ();
static unsigned int
rest_of_handle_partition_blocks (void)
{
- no_new_pseudos = 0;
partition_hot_cold_basic_blocks ();
- allocate_reg_life_data ();
- update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
- PROP_LOG_LINKS | PROP_REG_INFO | PROP_DEATH_NOTES);
- no_new_pseudos = 1;
return 0;
}