summaryrefslogtreecommitdiff
path: root/gcc/bb-reorder.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/bb-reorder.c')
-rw-r--r--gcc/bb-reorder.c151
1 files changed, 94 insertions, 57 deletions
diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c
index 90c14547aa6..32234b103f5 100644
--- a/gcc/bb-reorder.c
+++ b/gcc/bb-reorder.c
@@ -197,8 +197,10 @@ push_to_next_round_p (basic_block bb, int round, int number_of_rounds,
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);
@@ -207,7 +209,11 @@ push_to_next_round_p (basic_block bb, int round, int number_of_rounds,
|| 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
@@ -383,7 +389,9 @@ rotate_loop (edge back_edge, struct trace *trace, int trace_n)
/* 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);
}
@@ -750,6 +758,8 @@ copy_bb (basic_block old_bb, edge e, basic_block bb, int trace)
basic_block new_bb;
new_bb = duplicate_block (old_bb, e);
+ new_bb->partition = old_bb->partition;
+
if (e->dest != new_bb)
abort ();
if (e->dest->rbi->visited)
@@ -1236,6 +1246,8 @@ add_unlikely_executed_notes (void)
{
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);
@@ -1251,6 +1263,7 @@ find_rarely_executed_basic_blocks_and_crossing_edges (edge *crossing_edges,
int *max_idx)
{
basic_block bb;
+ bool has_hot_blocks = false;
edge e;
int i;
@@ -1261,32 +1274,49 @@ find_rarely_executed_basic_blocks_and_crossing_edges (edge *crossing_edges,
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;
}
@@ -1301,32 +1331,28 @@ mark_bb_for_unlikely_executed_section (basic_block bb)
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 (!NOTE_P (cur_insn)
- && !LABEL_P (cur_insn))
+ 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;
@@ -1754,7 +1780,7 @@ fix_crossing_unconditional_branches (void)
rtx new_reg;
rtx cur_insn;
edge succ;
-
+
FOR_EACH_BB (cur_bb)
{
last_insn = BB_END (cur_bb);
@@ -1886,26 +1912,36 @@ fix_edges_for_rarely_executed_code (edge *crossing_edges,
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. FLAGS is
@@ -1957,7 +1993,8 @@ reorder_basic_blocks (unsigned int flags)
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 ();