+2004-08-25 Caroline Tice <ctice@apple.com>
+
+ * bb-reorder.c (partition_hot_cold_basic_blocks): Add more details
+ to comments at start of function.
+ * cfgbuild.c (make_edges): Add more details to hot/cold partitioning
+ comment.
+ * cfgcleanup.c (try_simplify_condjump, try_forward_edges,
+ merge_blocks_move_predecessor_nojumps,
+ merge_blocks_move_successor_nojumps, merge_blocks_move,
+ try_crossjump_to_edge, try_crossjump_bb): Likewise.
+ * cfglayout.c (fixup_reorder_chain): Likewise.
+ * cfgrtl.c (rtl_can_merge_blocks, try_redirect_by_replacing_jump,
+ cfg_layout_can_merge_blocks_p): Likewise.
+ * ifcvt.c (find_if_case_1, find_if_case_2): Likewise.
+ * passes.c (rest_of_compilation): Update comments for calling
+ optimization that partitions hot/cold basic blocks.
+ * doc/invoke.texi: Update documentation of
+ freorder-blocks-and-partition flag.
+
2004-08-25 Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips.md (reg): Renamed mode attribute from ccreg.
been called. However part of this optimization may introduce new
register usage, so it must be called before register allocation has
occurred. This means that this optimization is actually called
- well before the optimization that reorders basic blocks (see function
- above).
+ well before the optimization that reorders basic blocks (see
+ function above).
This optimization checks the feedback information to determine
- which basic blocks are hot/cold and adds
- NOTE_INSN_UNLIKELY_EXECUTED_CODE to non-hot basic blocks. The
+ which basic blocks are hot/cold and causes reorder_basic_blocks to
+ add NOTE_INSN_UNLIKELY_EXECUTED_CODE to non-hot basic blocks. The
presence or absence of this note is later used for writing out
- sections in the .o file. This optimization must also modify the
- CFG to make sure there are no fallthru edges between hot & cold
- blocks, as those blocks will not necessarily be contiguous in the
- .o (or assembly) file; and in those cases where the architecture
- requires it, conditional and unconditional branches that cross
- between sections are converted into unconditional or indirect
- jumps, depending on what is appropriate. */
+ sections in the .o file. Because hot and cold sections can be
+ arbitrarily large (within the bounds of memory), far beyond the
+ size of a single function, it is necessary to fix up all edges that
+ cross section boundaries, to make sure the instructions used can
+ actually span the required distance. The fixes are described
+ below.
+
+ Fall-through edges must be changed into jumps; it is not safe or
+ legal to fall through across a section boundary. Whenever a
+ fall-through edge crossing a section boundary is encountered, a new
+ basic block is inserted (in the same section as the fall-through
+ source), and the fall through edge is redirected to the new basic
+ block. The new basic block contains an unconditional jump to the
+ original fall-through target. (If the unconditional jump is
+ insufficient to cross section boundaries, that is dealt with a
+ little later, see below).
+
+ In order to deal with architectures that have short conditional
+ branches (which cannot span all of memory) we take any conditional
+ jump that attempts to cross a section boundary and add a level of
+ indirection: it becomes a conditional jump to a new basic block, in
+ the same section. The new basic block contains an unconditional
+ jump to the original target, in the other section.
+
+ For those architectures whose unconditional branch is also
+ incapable of reaching all of memory, those unconditional jumps are
+ converted into indirect jumps, through a register.
+
+ IMPORTANT NOTE: This optimization causes some messy interactions
+ with the cfg cleanup optimizations; those optimizations want to
+ merge blocks wherever possible, and to collapse indirect jump
+ sequences (change "A jumps to B jumps to C" directly into "A jumps
+ to C"). Those optimizations can undo the jump fixes that
+ partitioning is required to make (see above), in order to ensure
+ that jumps attempting to cross section boundaries are really able
+ to cover whatever distance the jump requires (on many architectures
+ conditional or unconditional jumps are not able to reach all of
+ memory). Therefore tests have to be inserted into each such
+ optimization to make sure that it does not undo stuff necessary to
+ cross partition boundaries. This would be much less of a problem
+ if we could perform this optimization later in the compilation, but
+ unfortunately the fact that we may need to create indirect jumps
+ (through registers) requires that this optimization be performed
+ before register allocation. */
void
partition_hot_cold_basic_blocks (void)
current_function_has_computed_jump = 0;
/* If we are partitioning hot and cold basic blocks into separate
- sections, we cannot assume there is no computed jump. */
+ sections, we cannot assume there is no computed jump (partitioning
+ sometimes requires the use of indirect jumps; see comments about
+ partitioning at the top of bb-reorder.c:partition_hot_cold_basic_blocks
+ for complete details). */
if (flag_reorder_blocks_and_partition)
current_function_has_computed_jump = 1;
/* If we are partitioning hot/cold basic blocks, we don't want to
mess up unconditional or indirect jumps that cross between hot
- and cold sections. */
+ and cold sections.
+
+ Basic block partitioning may result in some jumps that appear to
+ be optimizable (or blocks that appear to be mergeable), but which really
+ must be left untouched (they are required to make it safely across
+ partition boundaries). See the comments at the top of
+ bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
if (flag_reorder_blocks_and_partition
&& (BB_PARTITION (jump_block) != BB_PARTITION (jump_dest_block)
/* If we are partitioning hot/cold basic blocks, we don't want to
mess up unconditional or indirect jumps that cross between hot
- and cold sections. */
+ and cold sections.
+ Basic block partitioning may result in some jumps that appear to
+ be optimizable (or blocks that appear to be mergeable), but which really m
+ ust be left untouched (they are required to make it safely across
+ partition boundaries). See the comments at the top of
+ bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
+
if (flag_reorder_blocks_and_partition
&& find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX))
return false;
counter = 0;
/* If we are partitioning hot/cold basic_blocks, we don't want to mess
- up jumps that cross between hot/cold sections. */
+ up jumps that cross between hot/cold sections.
+
+ Basic block partitioning may result in some jumps that appear
+ to be optimizable (or blocks that appear to be mergeable), but which
+ really must be left untouched (they are required to make it safely
+ across partition boundaries). See the comments at the top of
+ bb-reorder.c:partition_hot_cold_basic_blocks for complete
+ details. */
if (flag_reorder_blocks_and_partition
&& first != EXIT_BLOCK_PTR
/* If we are partitioning hot/cold basic blocks, we don't want to
mess up unconditional or indirect jumps that cross between hot
- and cold sections. */
+ and cold sections.
+ Basic block partitioning may result in some jumps that appear to
+ be optimizable (or blocks that appear to be mergeable), but which really
+ must be left untouched (they are required to make it safely across
+ partition boundaries). See the comments at the top of
+ bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
+
if (flag_reorder_blocks_and_partition
&& (BB_PARTITION (a) != BB_PARTITION (b)
|| find_reg_note (BB_END (a), REG_CROSSING_JUMP, NULL_RTX)))
/* If we are partitioning hot/cold basic blocks, we don't want to
mess up unconditional or indirect jumps that cross between hot
- and cold sections. */
+ and cold sections.
+ Basic block partitioning may result in some jumps that appear to
+ be optimizable (or blocks that appear to be mergeable), but which really
+ must be left untouched (they are required to make it safely across
+ partition boundaries). See the comments at the top of
+ bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
+
if (flag_reorder_blocks_and_partition
&& (find_reg_note (BB_END (a), REG_CROSSING_JUMP, NULL_RTX)
|| BB_PARTITION (a) != BB_PARTITION (b)))
/* If we are partitioning hot/cold basic blocks, we don't want to
mess up unconditional or indirect jumps that cross between hot
- and cold sections. */
+ and cold sections.
+ Basic block partitioning may result in some jumps that appear to
+ be optimizable (or blocks that appear to be mergeable), but which really
+ must be left untouched (they are required to make it safely across
+ partition boundaries). See the comments at the top of
+ bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
+
if (flag_reorder_blocks_and_partition
&& (find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX)
|| find_reg_note (BB_END (c), REG_CROSSING_JUMP, NULL_RTX)
newpos1 = newpos2 = NULL_RTX;
/* If we have partitioned hot/cold basic blocks, it is a bad idea
- to try this optimization. */
+ to try this optimization.
+
+ Basic block partitioning may result in some jumps that appear to
+ be optimizable (or blocks that appear to be mergeable), but which really
+ must be left untouched (they are required to make it safely across
+ partition boundaries). See the comments at the top of
+ bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
if (flag_reorder_blocks_and_partition && no_new_pseudos)
return false;
/* If we are partitioning hot/cold basic blocks, we don't want to
mess up unconditional or indirect jumps that cross between hot
- and cold sections. */
+ and cold sections.
+ Basic block partitioning may result in some jumps that appear to
+ be optimizable (or blocks that appear to be mergeable), but which really
+ must be left untouched (they are required to make it safely across
+ partition boundaries). See the comments at the top of
+ bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
+
if (flag_reorder_blocks_and_partition
&& (BB_PARTITION (bb->pred->src) != BB_PARTITION (bb->pred->pred_next->src)
|| (bb->pred->flags & EDGE_CROSSING)))
bb = nb;
/* Make sure new bb is tagged for correct section (same as
- fall-thru source). */
+ fall-thru source, since you cannot fall-throu across
+ section boundaries). */
BB_COPY_PARTITION (e_fall->src, bb->pred->src);
if (flag_reorder_blocks_and_partition
&& targetm.have_named_sections)
mess up unconditional or indirect jumps that cross between hot
and cold sections.
- ??? If two basic blocks could otherwise be merged (which implies
- that the jump between the two is unconditional), and one is in a
- hot section and the other is in a cold section, surely that means
- that one of the section choices is wrong. */
+ Basic block partitioning may result in some jumps that appear to
+ be optimizable (or blocks that appear to be mergeable), but which really
+ must be left untouched (they are required to make it safely across
+ partition boundaries). See the comments at the top of
+ bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
if (flag_reorder_blocks_and_partition
&& (find_reg_note (BB_END (a), REG_CROSSING_JUMP, NULL_RTX)
/* If we are partitioning hot/cold basic blocks, we don't want to
mess up unconditional or indirect jumps that cross between hot
- and cold sections. */
+ and cold sections.
+
+ Basic block partitioning may result in some jumps that appear to
+ be optimizable (or blocks that appear to be mergeable), but which really
+ must be left untouched (they are required to make it safely across
+ partition boundaries). See the comments at the top of
+ bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
if (flag_reorder_blocks_and_partition
&& (find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)
mess up unconditional or indirect jumps that cross between hot
and cold sections.
- ??? If two basic blocks could otherwise be merged (which implies
- that the jump between the two is unconditional), and one is in a
- hot section and the other is in a cold section, surely that means
- that one of the section choices is wrong. */
-
+ Basic block partitioning may result in some jumps that appear to
+ be optimizable (or blocks that appear to be mergeable), but which really
+ must be left untouched (they are required to make it safely across
+ partition boundaries). See the comments at the top of
+ bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
+
if (flag_reorder_blocks_and_partition
&& (find_reg_note (BB_END (a), REG_CROSSING_JUMP, NULL_RTX)
|| find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX)
into separate sections of the assembly and .o files, to improve
paging and cache locality performance.
+This optimization is automatically turned off in the presence of
+exception handling, for linkonce sections, for functions with a user-defined
+section attribute and on any architecture that does not support named
+sections.
+
@item -freorder-functions
@opindex freorder-functions
Reorder basic blocks in the compiled function in order to reduce number of
/* If we are partitioning hot/cold basic blocks, we don't want to
mess up unconditional or indirect jumps that cross between hot
- and cold sections. */
+ and cold sections.
+ Basic block partitioning may result in some jumps that appear to
+ be optimizable (or blocks that appear to be mergeable), but which really
+ must be left untouched (they are required to make it safely across
+ partition boundaries). See the comments at the top of
+ bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
+
if (flag_reorder_blocks_and_partition
&& ((BB_END (then_bb)
&& find_reg_note (BB_END (then_bb), REG_CROSSING_JUMP, NULL_RTX))
{
new_bb->index = then_bb_index;
BASIC_BLOCK (then_bb_index) = new_bb;
+ /* Since the fallthru edge was redirected from test_bb to new_bb,
+ we need to ensure that new_bb is in the same partition as
+ test bb (you can not fall through across section boundaries). */
BB_COPY_PARTITION (new_bb, test_bb);
}
/* We've possibly created jump to next insn, cleanup_cfg will solve that
/* If we are partitioning hot/cold basic blocks, we don't want to
mess up unconditional or indirect jumps that cross between hot
- and cold sections. */
+ and cold sections.
+ Basic block partitioning may result in some jumps that appear to
+ be optimizable (or blocks that appear to be mergeable), but which really
+ must be left untouched (they are required to make it safely across
+ partition boundaries). See the comments at the top of
+ bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
+
if (flag_reorder_blocks_and_partition
&& ((BB_END (then_bb)
&& find_reg_note (BB_END (then_bb), REG_CROSSING_JUMP, NULL_RTX))
rest_of_handle_if_after_combine ();
/* The optimization to partition hot/cold basic blocks into separate
- sections of the .o file does not work well with exception handling.
- Don't call it if there are exceptions. */
+ sections of the .o file does not work well with linkonce or with
+ user defined section attributes. Don't call it if either case
+ arises. */
if (flag_reorder_blocks_and_partition
&& !DECL_ONE_ONLY (current_function_decl)