diff options
author | ctice <ctice@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-08-18 16:22:08 +0000 |
---|---|---|
committer | ctice <ctice@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-08-18 16:22:08 +0000 |
commit | 065efcb175f104e463b1715a38244378d60bcf07 (patch) | |
tree | c63a7ba63b9528cef9f1bb15e12b69de24533c51 /gcc/bb-reorder.c | |
parent | d6a99b4bbc51fb9508bdf93ba61cec064d6e4c36 (diff) | |
download | gcc-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.c | 151 |
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 (); |