summaryrefslogtreecommitdiff
path: root/gcc/bb-reorder.c
diff options
context:
space:
mode:
authorctice <ctice@138bc75d-0d04-0410-961f-82ee72b054a4>2004-08-18 16:22:08 +0000
committerctice <ctice@138bc75d-0d04-0410-961f-82ee72b054a4>2004-08-18 16:22:08 +0000
commit065efcb175f104e463b1715a38244378d60bcf07 (patch)
treec63a7ba63b9528cef9f1bb15e12b69de24533c51 /gcc/bb-reorder.c
parentd6a99b4bbc51fb9508bdf93ba61cec064d6e4c36 (diff)
downloadgcc-065efcb175f104e463b1715a38244378d60bcf07.tar.gz
Hot/cold partitioning update patch. The problems that this patch
attemptd to address/fix are: - Fix places where adding in_unlikely_executed_text to the enum data type "in_section" threw off switch case statements. - Make it work correctly (by turning it off) for functions where user specifies "__attribute__ section" - Make it work correctly (by turning it off) for linkonce sections - Make it work correctly with -ffunction-sections flag - Make it output correct cold section labels - Undo some changes to original assembly code generation - Turn off hot/cold partitioning in the presence of DWARF debugging (for the moment) - Turn off hot/cold partitioning for architectures that do not support named sections - Use variables rather than constants for cold section labels and names (to work correctly with -ffunction-sections, among other things) 2004-08-18 Caroline Tice <ctice@apple.com> * Makefile.in (STAGEFEEDBACK_FLAGS_TO_PASS) Add "-freorder-blocks-and-partition" to the flags used in second stage of profiledbootstrap. * bb-reorder.c (push_to_next_round_p): Add new variable, next_round_is_last; set and use variable to make sure, when partitioning, that the last trace construction round consists of all (and only) cold basic blocks. (rotate_loop): Don't copy blocks that end in a section crossing jump. (copy_bb): Correctly initialize "partition" of duplicated bb. (add_unlikely_executed_notes): Add a comment. (find_rarely_executed_basic_blocks_and_crossing_edges): Modify to make sure, if function contains hot blocks, that the successors of ENTRY_BLOCK_PTR are hot; also, only look for crossing edges if the architecture supports named sections. (mark_bb_for_unlikely_executed_section): Modify to always insert the NOTE_INSN_UNLIKELY_EXECUTED_CODE immediately after the basic block note insn. (fix_crossing_unconditional_branches): Remove extra space. (fix_edges_for_rarely_executed_code): Modify to only do partitioning work if the architecture supports named sections. (reorder_basic_blocks): Modify to only add NOTE_INSN_UNLIKELY_EXECUTED_CODE notes if the architecture supports named sections. * c-common.c (handle_section_attribute): Initialize new global variable, user_defined_section_attribute, to true if user has specified one. * cfgcleanup.c (try_forward_edges): Modify to not attempt to forward edges that cross section boundaries. * cfglayout.c (fixup_reorder_chain): Modify to only fix up partitioning information if the architecture supports named sections. * cfgrtl.c (target.h): Add statement to include this. (rtl_split_block): Make sure newly created bb gets correct partition. (try_redirect_by_replacing_jump): Make sure redirection isn't attempting to cross section boundaries. (force_nonfallthru_and_redirect): Only do partition fix up if architecture supports named sections. (rtl_split_edge): Make sure newly created bb ends up in correct partition. (commit_one_edge_insertion): Remove code that incorrectly updated basic block partition; Make sure partition fix up only happens if architecture supports named sections and it's not already done. (rtl_verify_flow_info_1): Fix if-condition on test/error condition that fallthru edges are not allowed to cross section boundaries. * defaults.h (NORMAL_TEXT_SECTION_NAME): Remove this. * final.c (final_scan_insn): Remove redundant test from if-statement; change calls to text_section into calls to function_section; add code to only to partitioning fix up if architecture supports named sections. * ifcvt.c (find_if_case_1): Make sure newly created bb has correct partition. (if_convert): Add targetm.have_named_sections to test. * output.h (unlikely_section_label): Extern declaration for new global variable. (unlikely_text_section_name): Likewise. * opts.c (decode_options): If both partitioning and DWARF debugging are turned on, issue a warning that this doesn't work, and change partitiong to basic block reordering (without hot/cold partitions). * passes.c (rest_of_handle_final): Re-set new global variable, user_defined_section_attribute, to false. (rest_of_compilation): Change options for calling partitioning function: Don't call if the user defined the section attribute, and don't call if DECL_ONE_ONLY is true for the current function. * predict.c (choose_function_section): Return immediately if we are doing hot/cold partitioning (i.e. let the basic block partitioning determine where the function belongs). * reg-stack.c (emit_swap_insn): Add condition to step over NOTE_INSN_UNLIKELY_EXECUTED_CODE notes. * toplev.c (user_defined_section_attribute): New global variable. * toplev.h (user_defined_section_attribute): Extern declaration for new global variable. * varasm.c (unlikely_section_label): New global variable. (unlikely_text_section_name): New global variable. (unlikely_text_section): Add code to initialize unlikely_text_section_name if necessary; modify to use unlikely_text_section_name and unlikely_section_label; also to use named_section properly. (in_unlikely_text_section): Modify to work correctly with named_section and to use unlikely_text_section_name. (named_section): Add code to work properly with cold section. (function_section): Clean up if-statement. * config/darwin.c (darwin_asm_named_section): Return to original code, removing use of SECTION_FORMAT_STRING. * config/arm/pe.h (switch_to_section): Add case for in_unlikely_executed_text to switch statement. * config/i386/cygming.h (switch_to_section): Likewise. * config/i386/darwin.h (NORMAL_TEXT_SECTION_NAME): Remove. (SECTION_FORMAT_STRING): Likewise. * config/mcore/mcore.h (switch_to_section): Likewise. * config/rs6000/darwin.h (NORMAL_TEXT_SECTION_NAME): Remove. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@86189 138bc75d-0d04-0410-961f-82ee72b054a4
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 ();