bool there_exists_another_round;
bool cold_block;
bool block_not_hot_enough;
+ bool next_round_is_last;
there_exists_another_round = round < number_of_rounds - 1;
+ next_round_is_last = round + 1 == number_of_rounds - 1;
cold_block = (flag_reorder_blocks_and_partition
&& bb->partition == COLD_PARTITION);
|| bb->count < count_th
|| probably_never_executed_bb_p (bb));
- if (there_exists_another_round
+ if (flag_reorder_blocks_and_partition
+ && next_round_is_last
+ && bb->partition != COLD_PARTITION)
+ return false;
+ else if (there_exists_another_round
&& (cold_block || block_not_hot_enough))
return true;
else
/* Duplicate HEADER if it is a small block containing cond jump
in the end. */
- if (any_condjump_p (BB_END (header)) && copy_bb_p (header, 0))
+ if (any_condjump_p (BB_END (header)) && copy_bb_p (header, 0)
+ && !find_reg_note (BB_END (header), REG_CROSSING_JUMP,
+ NULL_RTX))
{
copy_bb (header, prev_bb->succ, prev_bb, trace_n);
}
{
basic_block new_bb;
- new_bb = cfg_layout_duplicate_bb (old_bb, e);
+ new_bb = duplicate_block (old_bb, e);
+ new_bb->partition = old_bb->partition;
+
if (e->dest != new_bb)
abort ();
if (e->dest->rbi->visited)
last_trace = -1;
/* If we are partitioning hot/cold basic blocks, mark the cold
- traces as already connnected, to remove them from consideration
+ traces as already connected, to remove them from consideration
for connection to the hot traces. After the hot traces have all
been connected (determined by "unconnected_hot_trace_count"), we
will go back and connect the cold traces. */
}
FREE (connected);
+ FREE (cold_traces);
}
/* Return true when BB can and should be copied. CODE_MAY_GROW is true
return false;
if (!bb->pred || !bb->pred->pred_next)
return false;
- if (!cfg_layout_can_duplicate_bb_p (bb))
+ if (!can_duplicate_block_p (bb))
return false;
/* Avoid duplicating blocks which have many successors (PR/13430). */
{
basic_block bb;
+ /* Add the UNLIKELY_EXECUTED_NOTES to each cold basic block. */
+
FOR_EACH_BB (bb)
if (bb->partition == COLD_PARTITION)
mark_bb_for_unlikely_executed_section (bb);
int *max_idx)
{
basic_block bb;
+ bool has_hot_blocks = false;
edge e;
int i;
if (probably_never_executed_bb_p (bb))
bb->partition = COLD_PARTITION;
else
- bb->partition = HOT_PARTITION;
+ {
+ bb->partition = HOT_PARTITION;
+ has_hot_blocks = true;
+ }
}
+ /* Since all "hot" basic blocks will eventually be scheduled before all
+ cold basic blocks, make *sure* the real function entry block is in
+ the hot partition (if there is one). */
+
+ if (has_hot_blocks)
+ for (e = ENTRY_BLOCK_PTR->succ; e; e = e->succ_next)
+ if (e->dest->index >= 0)
+ {
+ e->dest->partition = HOT_PARTITION;
+ break;
+ }
+
/* Mark every edge that crosses between sections. */
i = 0;
- FOR_EACH_BB (bb)
- for (e = bb->succ; e; e = e->succ_next)
- {
- if (e->src != ENTRY_BLOCK_PTR
- && e->dest != EXIT_BLOCK_PTR
- && e->src->partition != e->dest->partition)
+ if (targetm.have_named_sections)
+ {
+ FOR_EACH_BB (bb)
+ for (e = bb->succ; e; e = e->succ_next)
{
- e->crossing_edge = true;
- if (i == *max_idx)
+ if (e->src != ENTRY_BLOCK_PTR
+ && e->dest != EXIT_BLOCK_PTR
+ && e->src->partition != e->dest->partition)
{
- *max_idx *= 2;
- crossing_edges = xrealloc (crossing_edges,
- (*max_idx) * sizeof (edge));
+ e->crossing_edge = true;
+ if (i == *max_idx)
+ {
+ *max_idx *= 2;
+ crossing_edges = xrealloc (crossing_edges,
+ (*max_idx) * sizeof (edge));
+ }
+ crossing_edges[i++] = e;
}
- crossing_edges[i++] = e;
+ else
+ e->crossing_edge = false;
}
- else
- e->crossing_edge = false;
- }
-
+ }
*n_crossing_edges = i;
}
rtx insert_insn = NULL;
rtx new_note;
- /* Find first non-note instruction and insert new NOTE before it (as
- long as new NOTE is not first instruction in basic block). */
-
- for (cur_insn = BB_HEAD (bb); cur_insn != NEXT_INSN (BB_END (bb));
+ /* Insert new NOTE immediately after BASIC_BLOCK note. */
+
+ for (cur_insn = BB_HEAD (bb); cur_insn != NEXT_INSN (BB_END (bb));
cur_insn = NEXT_INSN (cur_insn))
- if (GET_CODE (cur_insn) != NOTE
- && GET_CODE (cur_insn) != CODE_LABEL)
+ if (GET_CODE (cur_insn) == NOTE
+ && NOTE_LINE_NUMBER (cur_insn) == NOTE_INSN_BASIC_BLOCK)
{
insert_insn = cur_insn;
break;
}
-
+
+ /* If basic block does not contain a NOTE_INSN_BASIC_BLOCK, there is
+ a major problem. */
+
+ if (!insert_insn)
+ abort ();
+
/* Insert note and assign basic block number to it. */
- if (insert_insn)
- {
- new_note = emit_note_before (NOTE_INSN_UNLIKELY_EXECUTED_CODE,
- insert_insn);
- NOTE_BASIC_BLOCK (new_note) = bb;
- }
- else
- {
- new_note = emit_note_after (NOTE_INSN_UNLIKELY_EXECUTED_CODE,
- BB_END (bb));
- NOTE_BASIC_BLOCK (new_note) = bb;
- }
+ new_note = emit_note_after (NOTE_INSN_UNLIKELY_EXECUTED_CODE,
+ insert_insn);
+ NOTE_BASIC_BLOCK (new_note) = bb;
}
/* If any destination of a crossing edge does not have a label, add label;
Convert any fall-through crossing edges (for blocks that do not contain
- a jump) to unconditional jumps. */
+ a jump) to unconditional jumps. */
static void
add_labels_and_missing_jumps (edge *crossing_edges, int n_crossing_edges)
if (src && (src != ENTRY_BLOCK_PTR))
{
- if (GET_CODE (BB_END (src)) != JUMP_INSN)
+ if (!JUMP_P (BB_END (src)))
/* bb just falls through. */
{
/* make sure there's only one successor */
edge succ1;
edge succ2;
edge fall_thru;
- edge cond_jump;
+ edge cond_jump = NULL;
edge e;
bool cond_jump_crosses;
int invert_worked;
&& cur_bb->rbi->next == cond_jump->dest)
{
/* Find label in fall_thru block. We've already added
- any missing labels, so there must be one. */
+ any missing labels, so there must be one. */
fall_thru_label = block_label (fall_thru->dest);
/* Check each predecessor to see if it has a label, and contains
only one executable instruction, which is an unconditional jump.
- If so, we can use it. */
+ If so, we can use it. */
- if (GET_CODE (BB_HEAD (src)) == CODE_LABEL)
+ if (LABEL_P (BB_HEAD (src)))
for (insn = BB_HEAD (src);
!INSN_P (insn) && insn != NEXT_INSN (BB_END (src));
insn = NEXT_INSN (insn))
{
if (INSN_P (insn)
&& insn == BB_END (src)
- && GET_CODE (insn) == JUMP_INSN
+ && JUMP_P (insn)
&& !any_condjump_p (insn))
{
source_bb = src;
rtx new_reg;
rtx cur_insn;
edge succ;
-
+
FOR_EACH_BB (cur_bb)
{
last_insn = BB_END (cur_bb);
/* Check to see if bb ends in a crossing (unconditional) jump. At
this point, no crossing jumps should be conditional. */
- if (GET_CODE (last_insn) == JUMP_INSN
+ if (JUMP_P (last_insn)
&& succ->crossing_edge)
{
rtx label2, table;
cur_insn = NEXT_INSN (cur_insn))
{
BLOCK_FOR_INSN (cur_insn) = cur_bb;
- if (GET_CODE (cur_insn) == JUMP_INSN)
+ if (JUMP_P (cur_insn))
jump_insn = cur_insn;
}
FOR_EACH_BB (bb)
for (e = bb->succ; e; e = e->succ_next)
if (e->crossing_edge
- && GET_CODE (BB_END (e->src)) == JUMP_INSN)
+ && JUMP_P (BB_END (e->src)))
REG_NOTES (BB_END (e->src)) = gen_rtx_EXPR_LIST (REG_CROSSING_JUMP,
NULL_RTX,
REG_NOTES (BB_END
fix_up_fall_thru_edges ();
- /* If the architecture does not have conditional branches that can
- span all of memory, convert crossing conditional branches into
- crossing unconditional branches. */
-
- if (!HAS_LONG_COND_BRANCH)
- fix_crossing_conditional_branches ();
+ /* Only do the parts necessary for writing separate sections if
+ the target architecture has the ability to write separate sections
+ (i.e. it has named sections). Otherwise, the hot/cold partitioning
+ information will be used when reordering blocks to try to put all
+ the hot blocks together, then all the cold blocks, but no actual
+ section partitioning will be done. */
+
+ if (targetm.have_named_sections)
+ {
+ /* If the architecture does not have conditional branches that can
+ span all of memory, convert crossing conditional branches into
+ crossing unconditional branches. */
- /* If the architecture does not have unconditional branches that
- can span all of memory, convert crossing unconditional branches
- into indirect jumps. Since adding an indirect jump also adds
- a new register usage, update the register usage information as
- well. */
+ if (!HAS_LONG_COND_BRANCH)
+ fix_crossing_conditional_branches ();
- if (!HAS_LONG_UNCOND_BRANCH)
- {
- fix_crossing_unconditional_branches ();
- reg_scan (get_insns(), max_reg_num (), 1);
- }
+ /* If the architecture does not have unconditional branches that
+ can span all of memory, convert crossing unconditional branches
+ into indirect jumps. Since adding an indirect jump also adds
+ a new register usage, update the register usage information as
+ well. */
+
+ if (!HAS_LONG_UNCOND_BRANCH)
+ {
+ fix_crossing_unconditional_branches ();
+ reg_scan (get_insns(), max_reg_num (), 1);
+ }
- add_reg_crossing_jump_notes ();
+ add_reg_crossing_jump_notes ();
+ }
}
-/* Reorder basic blocks. The main entry point to this file. */
+/* Reorder basic blocks. The main entry point to this file. FLAGS is
+ the set of flags to pass to cfg_layout_initialize(). */
void
-reorder_basic_blocks (void)
+reorder_basic_blocks (unsigned int flags)
{
int n_traces;
int i;
timevar_push (TV_REORDER_BLOCKS);
- cfg_layout_initialize ();
+ cfg_layout_initialize (flags);
set_edge_can_fallthru_flag ();
mark_dfs_back_edges ();
if (dump_file)
dump_flow_info (dump_file);
- if (flag_reorder_blocks_and_partition)
+ if (flag_reorder_blocks_and_partition
+ && targetm.have_named_sections)
add_unlikely_executed_notes ();
cfg_layout_finalize ();
crossing_edges = xcalloc (max_edges, sizeof (edge));
- cfg_layout_initialize ();
+ cfg_layout_initialize (0);
FOR_EACH_BB (cur_bb)
if (cur_bb->index >= 0