aboutsummaryrefslogtreecommitdiff
path: root/gcc/cfgrtl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cfgrtl.c')
-rw-r--r--gcc/cfgrtl.c148
1 files changed, 146 insertions, 2 deletions
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 341167dd684..dcb155e0322 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -56,6 +56,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "insn-config.h"
#include "cfglayout.h"
#include "expr.h"
+#include "target.h"
/* Stubs in case we don't have a return insn. */
#ifndef HAVE_return
@@ -99,6 +100,9 @@ can_delete_note_p (rtx note)
{
return (NOTE_LINE_NUMBER (note) == NOTE_INSN_DELETED
|| NOTE_LINE_NUMBER (note) == NOTE_INSN_BASIC_BLOCK
+ /* APPLE LOCAL begin hot/cold partitioning */
+ || NOTE_LINE_NUMBER (note) == NOTE_INSN_UNLIKELY_EXECUTED_CODE
+ /* APPLE LOCAL end hot/cold partitioning */
|| NOTE_LINE_NUMBER (note) == NOTE_INSN_PREDICTION);
}
@@ -318,6 +322,9 @@ create_basic_block_structure (rtx head, rtx end, rtx bb_note, basic_block after)
link_block (bb, after);
BASIC_BLOCK (bb->index) = bb;
update_bb_for_insn (bb);
+ /* APPLE LOCAL begin hot/cold partitioning */
+ bb->partition = UNPARTITIONED;
+ /* APPLE LOCAL end hot/cold partitioning */
/* Tag the block so that we know it has been used when considering
other basic block notes. */
@@ -613,11 +620,28 @@ rtl_merge_blocks (basic_block a, basic_block b)
static bool
rtl_can_merge_blocks (basic_block a,basic_block b)
{
+ /* APPLE LOCAL begin hot/cold partitioning */
+ bool partitions_ok = true;
+
+ /* 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. */
+
+ 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)
+ || a->partition != b->partition))
+ partitions_ok = false;
+ /* APPLE LOCAL end hot/cold partitioning */
+
/* There must be exactly one edge in between the blocks. */
return (a->succ && !a->succ->succ_next && a->succ->dest == b
&& !b->pred->pred_next && a != b
/* Must be simple edge. */
&& !(a->succ->flags & EDGE_COMPLEX)
+ /* APPLE LOCAL begin hot/cold partitioning */
+ && partitions_ok
+ /* APPLE LOCAL end hot/cold partitioning */
&& a->next_bb == b
&& a != ENTRY_BLOCK_PTR && b != EXIT_BLOCK_PTR
/* If the jump insn has side effects,
@@ -658,6 +682,16 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
rtx set;
int fallthru = 0;
+ /* APPLE LOCAL begin hot/cold partitioning */
+ /* 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. */
+
+ if (flag_reorder_blocks_and_partition
+ && find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX))
+ return false;
+ /* APPLE LOCAL end hot/cold partitioning */
+
/* Verify that all targets will be TARGET. */
for (tmp = src->succ; tmp; tmp = tmp->succ_next)
if (tmp->dest != target && tmp != e)
@@ -1063,6 +1097,36 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
target->global_live_at_start);
}
+ /* APPLE LOCAL begin hot/cold partitioning */
+ /* Make sure new block ends up in correct hot/cold section. */
+
+ jump_block->partition = e->src->partition;
+ if (flag_reorder_blocks_and_partition
+ && targetm.have_named_sections)
+ {
+ if (e->src->partition == COLD_PARTITION)
+ {
+ rtx bb_note, new_note;
+ for (bb_note = BB_HEAD (jump_block);
+ bb_note && bb_note != NEXT_INSN (BB_END (jump_block));
+ bb_note = NEXT_INSN (bb_note))
+ if (GET_CODE (bb_note) == NOTE
+ && NOTE_LINE_NUMBER (bb_note) == NOTE_INSN_BASIC_BLOCK)
+ break;
+ new_note = emit_note_after (NOTE_INSN_UNLIKELY_EXECUTED_CODE,
+ bb_note);
+ NOTE_BASIC_BLOCK (new_note) = jump_block;
+ jump_block->partition = COLD_PARTITION;
+ }
+ if (GET_CODE (BB_END (jump_block)) == JUMP_INSN
+ && !any_condjump_p (BB_END (jump_block))
+ && jump_block->succ->crossing_edge )
+ REG_NOTES (BB_END (jump_block)) = gen_rtx_EXPR_LIST
+ (REG_CROSSING_JUMP, NULL_RTX,
+ REG_NOTES (BB_END (jump_block)));
+ }
+ /* APPLE LOCAL end hot/cold partitioning */
+
/* Wire edge in. */
new_edge = make_edge (e->src, jump_block, EDGE_FALLTHRU);
new_edge->probability = e->probability;
@@ -1477,6 +1541,12 @@ commit_one_edge_insertion (edge e, int watch_calls)
tmp = NEXT_INSN (tmp);
if (NOTE_INSN_BASIC_BLOCK_P (tmp))
tmp = NEXT_INSN (tmp);
+ /* APPLE LOCAL begin hot/cold partitioning */
+ if (tmp
+ && GET_CODE (tmp) == NOTE
+ && NOTE_LINE_NUMBER (tmp) == NOTE_INSN_UNLIKELY_EXECUTED_CODE)
+ tmp = NEXT_INSN (tmp);
+ /* APPLE LOCAL end hot/cold partitioning */
if (tmp == BB_HEAD (bb))
before = tmp;
else if (tmp)
@@ -1519,6 +1589,41 @@ commit_one_edge_insertion (edge e, int watch_calls)
{
bb = split_edge (e);
after = BB_END (bb);
+
+ /* APPLE LOCAL begin hot/cold partitioning */
+ /* If we are partitioning hot/cold basic blocks, we must make sure
+ that the new basic block ends up in the correct section. */
+
+ bb->partition = e->src->partition;
+ if (flag_reorder_blocks_and_partition
+ && targetm.have_named_sections
+ && e->src != ENTRY_BLOCK_PTR
+ && e->src->partition == COLD_PARTITION)
+ {
+ rtx bb_note, new_note, cur_insn;
+
+ bb_note = NULL_RTX;
+ 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
+ && NOTE_LINE_NUMBER (cur_insn) == NOTE_INSN_BASIC_BLOCK)
+ {
+ bb_note = cur_insn;
+ break;
+ }
+
+ new_note = emit_note_after (NOTE_INSN_UNLIKELY_EXECUTED_CODE,
+ bb_note);
+ NOTE_BASIC_BLOCK (new_note) = bb;
+ if (GET_CODE (BB_END (bb)) == JUMP_INSN
+ && !any_condjump_p (BB_END (bb))
+ && bb->succ->crossing_edge )
+ REG_NOTES (BB_END (bb)) = gen_rtx_EXPR_LIST
+ (REG_CROSSING_JUMP, NULL_RTX, REG_NOTES (BB_END (bb)));
+ if (after == bb_note)
+ after = new_note;
+ }
+ /* APPLE LOCAL end hot/cold partitioning */
}
}
@@ -1788,6 +1893,9 @@ update_br_prob_note (basic_block bb)
- tails of basic blocks (ensure that boundary is necessary)
- scans body of the basic block for JUMP_INSN, CODE_LABEL
and NOTE_INSN_BASIC_BLOCK
+ ** APPLE LOCAL begin hot/cold partitioning **
+ - verify that no fall_thru edge crosses hot/cold partition boundaries
+ ** APPLE LOCAL end hot/cold partitioning **
In future it can be extended check a lot of other stuff as well
(reachability of basic blocks, life information, etc. etc.). */
@@ -1875,7 +1983,17 @@ rtl_verify_flow_info_1 (void)
for (e = bb->succ; e; e = e->succ_next)
{
if (e->flags & EDGE_FALLTHRU)
- n_fallthru++, fallthru = e;
+ /* APPLE LOCAL begin hot/cold partitioning */
+ {
+ n_fallthru++, fallthru = e;
+ if (e->crossing_edge)
+ {
+ error ("Fallthru edge crosses section boundary (bb %i)",
+ e->src->index);
+ err = 1;
+ }
+ }
+ /* APPLE LOCAL end hot/cold partitioning */
if ((e->flags & ~(EDGE_DFS_BACK
| EDGE_CAN_FALLTHRU
@@ -2161,10 +2279,19 @@ purge_dead_edges (basic_block bb)
for (e = bb->succ; e; e = next)
{
next = e->succ_next;
+
if (e->flags & EDGE_EH)
{
if (can_throw_internal (BB_END (bb)))
- continue;
+ {
+ /* If the call was removed/moved somewhere else, cleanup the
+ EDGE_ABNORMAL_CALL flag. */
+ if ((e->flags & EDGE_ABNORMAL_CALL)
+ && GET_CODE (BB_END (bb)) != CALL_INSN)
+ e->flags &= ~EDGE_ABNORMAL_CALL;
+
+ continue;
+ }
}
else if (e->flags & EDGE_ABNORMAL_CALL)
{
@@ -2547,11 +2674,28 @@ cfg_layout_delete_block (basic_block bb)
static bool
cfg_layout_can_merge_blocks_p (basic_block a, basic_block b)
{
+ /* APPLE LOCAL begin hot/cold partitioning */
+ bool partitions_ok = true;
+
+ /* 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. */
+
+ 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)
+ || a->partition != b->partition))
+ partitions_ok = false;
+ /* APPLE LOCAL end hot/cold partitioning */
+
/* There must be exactly one edge in between the blocks. */
return (a->succ && !a->succ->succ_next && a->succ->dest == b
&& !b->pred->pred_next && a != b
/* Must be simple edge. */
&& !(a->succ->flags & EDGE_COMPLEX)
+ /* APPLE LOCAL begin hot/cold partitioning */
+ && partitions_ok
+ /* APPLE LOCAL end hot/cold partitioning */
&& a != ENTRY_BLOCK_PTR && b != EXIT_BLOCK_PTR
/* If the jump insn has side effects,
we can't kill the edge. */