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
int, fibheap_t *, int);
static basic_block copy_bb (basic_block, edge, basic_block, int);
static fibheapkey_t bb_to_key (basic_block);
-static bool better_edge_p (basic_block, edge, int, int, int, int, edge);
+static bool better_edge_p (const_basic_block, const_edge, int, int, int, int, const_edge);
static void connect_traces (int, struct trace *);
-static bool copy_bb_p (basic_block, int);
+static bool copy_bb_p (const_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 bool push_to_next_round_p (const_basic_block, int, int, int, gcov_type);
+static void find_rarely_executed_basic_blocks_and_crossing_edges (edge **,
int *,
int *);
static void add_labels_and_missing_jumps (edge *, int);
current round of trace collection. */
static bool
-push_to_next_round_p (basic_block bb, int round, int number_of_rounds,
+push_to_next_round_p (const_basic_block bb, int round, int number_of_rounds,
int exec_th, gcov_type count_th)
{
bool there_exists_another_round;
BEST_PROB; similarly for frequency. */
static bool
-better_edge_p (basic_block bb, edge e, int prob, int freq, int best_prob,
- int best_freq, edge cur_best_edge)
+better_edge_p (const_basic_block bb, const_edge e, int prob, int freq, int best_prob,
+ int best_freq, const_edge cur_best_edge)
{
bool is_better_edge;
when code size is allowed to grow by duplication. */
static bool
-copy_bb_p (basic_block bb, int code_may_grow)
+copy_bb_p (const_basic_block bb, int code_may_grow)
{
int size = 0;
int max_size = uncond_jump_length;
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
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func, /* todo_flags_finish */
+ TODO_dump_func | TODO_verify_rtl_sharing,/* todo_flags_finish */
0 /* letter */
};
&& 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);
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)
+ if (flag_reorder_blocks || flag_reorder_blocks_and_partition)
{
- timevar_push (TV_TRACER);
- tracer (liveness_flags);
- timevar_pop (TV_TRACER);
+ reorder_basic_blocks ();
+ cleanup_cfg (CLEANUP_EXPENSIVE);
}
- if (flag_reorder_blocks || flag_reorder_blocks_and_partition)
- reorder_basic_blocks (liveness_flags);
- 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);
-
- /* 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 ();
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func, /* todo_flags_finish */
+ TODO_dump_func | TODO_verify_rtl_sharing,/* todo_flags_finish */
'B' /* letter */
};
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;
}
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func, /* todo_flags_finish */
+ TODO_dump_func | TODO_verify_rtl_sharing,/* todo_flags_finish */
0 /* letter */
};