aboutsummaryrefslogtreecommitdiff
path: root/gcc/shrink-wrap.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/shrink-wrap.c')
-rw-r--r--gcc/shrink-wrap.c235
1 files changed, 46 insertions, 189 deletions
diff --git a/gcc/shrink-wrap.c b/gcc/shrink-wrap.c
index fe795196709..b85b1c3b349 100644
--- a/gcc/shrink-wrap.c
+++ b/gcc/shrink-wrap.c
@@ -529,30 +529,49 @@ can_dup_for_shrink_wrapping (basic_block bb, basic_block pro, unsigned max_size)
return true;
}
-/* If the source of edge E has more than one successor, the verifier for
- branch probabilities gets confused by the fake edges we make where
- simple_return statements will be inserted later (because those are not
- marked as fallthrough edges). Fix this by creating an extra block just
- for that fallthrough. */
+/* Do whatever needs to be done for exits that run without prologue.
+ Sibcalls need nothing done. Normal exits get a simple_return inserted. */
-static edge
-fix_fake_fallthrough_edge (edge e)
+static void
+handle_simple_exit (edge e)
{
- if (EDGE_COUNT (e->src->succs) <= 1)
- return e;
- basic_block old_bb = e->src;
- rtx_insn *end = BB_END (old_bb);
- rtx_note *note = emit_note_after (NOTE_INSN_DELETED, end);
- basic_block new_bb = create_basic_block (note, note, old_bb);
- BB_COPY_PARTITION (new_bb, old_bb);
- BB_END (old_bb) = end;
+ if (e->flags & EDGE_SIBCALL)
+ {
+ /* Tell function.c to take no further action on this edge. */
+ e->flags |= EDGE_IGNORE;
- redirect_edge_succ (e, new_bb);
- e->flags |= EDGE_FALLTHRU;
- e->flags &= ~EDGE_FAKE;
+ e->flags &= ~EDGE_FALLTHRU;
+ emit_barrier_after_bb (e->src);
+ return;
+ }
- return make_edge (new_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_FAKE);
+ /* If the basic block the edge comes from has multiple successors,
+ split the edge. */
+ if (EDGE_COUNT (e->src->succs) > 1)
+ {
+ basic_block old_bb = e->src;
+ rtx_insn *end = BB_END (old_bb);
+ rtx_note *note = emit_note_after (NOTE_INSN_DELETED, end);
+ basic_block new_bb = create_basic_block (note, note, old_bb);
+ BB_COPY_PARTITION (new_bb, old_bb);
+ BB_END (old_bb) = end;
+
+ redirect_edge_succ (e, new_bb);
+ e->flags |= EDGE_FALLTHRU;
+
+ e = make_edge (new_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
+ }
+
+ e->flags &= ~EDGE_FALLTHRU;
+ rtx_jump_insn *ret = emit_jump_insn_after (targetm.gen_simple_return (),
+ BB_END (e->src));
+ JUMP_LABEL (ret) = simple_return_rtx;
+ emit_barrier_after_bb (e->src);
+
+ if (dump_file)
+ fprintf (dump_file, "Made simple_return with UID %d in bb %d\n",
+ INSN_UID (ret), e->src->index);
}
/* Try to perform a kind of shrink-wrapping, making sure the
@@ -610,13 +629,10 @@ fix_fake_fallthrough_edge (edge e)
(bb 4 is duplicated to 5; the prologue is inserted on the edge 5->3).
ENTRY_EDGE is the edge where the prologue will be placed, possibly
- changed by this function. BB_WITH is a bitmap that, if we do shrink-
- wrap, will on return contain the interesting blocks that run with
- prologue. PROLOGUE_SEQ is the prologue we will insert. */
+ changed by this function. PROLOGUE_SEQ is the prologue we will insert. */
void
-try_shrink_wrapping (edge *entry_edge, bitmap_head *bb_with,
- rtx_insn *prologue_seq)
+try_shrink_wrapping (edge *entry_edge, rtx_insn *prologue_seq)
{
/* If we cannot shrink-wrap, are told not to shrink-wrap, or it makes
no sense to shrink-wrap: then do not shrink-wrap! */
@@ -739,6 +755,7 @@ try_shrink_wrapping (edge *entry_edge, bitmap_head *bb_with,
reachable from PRO that we already found, and in VEC a stack of
those we still need to consider (to find successors). */
+ bitmap bb_with = BITMAP_ALLOC (NULL);
bitmap_set_bit (bb_with, pro->index);
vec<basic_block> vec;
@@ -851,6 +868,7 @@ try_shrink_wrapping (edge *entry_edge, bitmap_head *bb_with,
if (pro == entry)
{
+ BITMAP_FREE (bb_with);
free_dominance_info (CDI_DOMINATORS);
return;
}
@@ -946,22 +964,13 @@ try_shrink_wrapping (edge *entry_edge, bitmap_head *bb_with,
redirect_edge_and_branch_force (e, (basic_block) e->dest->aux);
}
- /* Change all the exits that should get a simple_return to FAKE.
- They will be converted later. */
+ /* Make a simple_return for those exits that run without prologue. */
- FOR_EACH_BB_FN (bb, cfun)
+ FOR_EACH_BB_REVERSE_FN (bb, cfun)
if (!bitmap_bit_p (bb_with, bb->index))
FOR_EACH_EDGE (e, ei, bb->succs)
if (e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
- {
- e = fix_fake_fallthrough_edge (e);
-
- e->flags &= ~EDGE_FALLTHRU;
- if (!(e->flags & EDGE_SIBCALL))
- e->flags |= EDGE_FAKE;
-
- emit_barrier_after_bb (e->src);
- }
+ handle_simple_exit (e);
/* Finally, we want a single edge to put the prologue on. Make a new
block before the PRO block; the edge beteen them is the edge we want.
@@ -994,158 +1003,6 @@ try_shrink_wrapping (edge *entry_edge, bitmap_head *bb_with,
*entry_edge = make_single_succ_edge (new_bb, pro, EDGE_FALLTHRU);
force_nonfallthru (*entry_edge);
+ BITMAP_FREE (bb_with);
free_dominance_info (CDI_DOMINATORS);
}
-
-/* If we're allowed to generate a simple return instruction, then by
- definition we don't need a full epilogue. If the last basic
- block before the exit block does not contain active instructions,
- examine its predecessors and try to emit (conditional) return
- instructions. */
-
-edge
-get_unconverted_simple_return (edge exit_fallthru_edge, bitmap_head bb_flags,
- vec<edge> *unconverted_simple_returns,
- rtx_insn **returnjump)
-{
- if (optimize)
- {
- unsigned i, last;
-
- /* convert_jumps_to_returns may add to preds of the exit block
- (but won't remove). Stop at end of current preds. */
- last = EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds);
- for (i = 0; i < last; i++)
- {
- edge e = EDGE_I (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds, i);
- if (LABEL_P (BB_HEAD (e->src))
- && !bitmap_bit_p (&bb_flags, e->src->index)
- && !active_insn_between (BB_HEAD (e->src), BB_END (e->src)))
- *unconverted_simple_returns
- = convert_jumps_to_returns (e->src, true,
- *unconverted_simple_returns);
- }
- }
-
- if (exit_fallthru_edge != NULL
- && EDGE_COUNT (exit_fallthru_edge->src->preds) != 0
- && !bitmap_bit_p (&bb_flags, exit_fallthru_edge->src->index))
- {
- basic_block last_bb;
-
- last_bb = emit_return_for_exit (exit_fallthru_edge, true);
- *returnjump = BB_END (last_bb);
- exit_fallthru_edge = NULL;
- }
- return exit_fallthru_edge;
-}
-
-/* If there were branches to an empty LAST_BB which we tried to
- convert to conditional simple_returns, but couldn't for some
- reason, create a block to hold a simple_return insn and redirect
- those remaining edges. */
-
-void
-convert_to_simple_return (edge entry_edge, edge orig_entry_edge,
- bitmap_head bb_flags, rtx_insn *returnjump,
- vec<edge> unconverted_simple_returns)
-{
- edge e;
- edge_iterator ei;
-
- if (!unconverted_simple_returns.is_empty ())
- {
- basic_block simple_return_block_hot = NULL;
- basic_block simple_return_block_cold = NULL;
- edge pending_edge_hot = NULL;
- edge pending_edge_cold = NULL;
- basic_block exit_pred;
- int i;
-
- gcc_assert (entry_edge != orig_entry_edge);
-
- /* See if we can reuse the last insn that was emitted for the
- epilogue. */
- if (returnjump != NULL_RTX
- && JUMP_LABEL (returnjump) == simple_return_rtx)
- {
- e = split_block (BLOCK_FOR_INSN (returnjump), PREV_INSN (returnjump));
- if (BB_PARTITION (e->src) == BB_HOT_PARTITION)
- simple_return_block_hot = e->dest;
- else
- simple_return_block_cold = e->dest;
- }
-
- /* Also check returns we might need to add to tail blocks. */
- FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
- if (EDGE_COUNT (e->src->preds) != 0
- && (e->flags & EDGE_FAKE) != 0
- && !bitmap_bit_p (&bb_flags, e->src->index))
- {
- if (BB_PARTITION (e->src) == BB_HOT_PARTITION)
- pending_edge_hot = e;
- else
- pending_edge_cold = e;
- }
-
- /* Save a pointer to the exit's predecessor BB for use in
- inserting new BBs at the end of the function. Do this
- after the call to split_block above which may split
- the original exit pred. */
- exit_pred = EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb;
-
- FOR_EACH_VEC_ELT (unconverted_simple_returns, i, e)
- {
- basic_block *pdest_bb;
- edge pending;
-
- if (BB_PARTITION (e->src) == BB_HOT_PARTITION)
- {
- pdest_bb = &simple_return_block_hot;
- pending = pending_edge_hot;
- }
- else
- {
- pdest_bb = &simple_return_block_cold;
- pending = pending_edge_cold;
- }
-
- if (*pdest_bb == NULL && pending != NULL)
- {
- emit_return_into_block (true, pending->src);
- pending->flags &= ~(EDGE_FALLTHRU | EDGE_FAKE);
- *pdest_bb = pending->src;
- }
- else if (*pdest_bb == NULL)
- {
- basic_block bb;
-
- bb = create_basic_block (NULL, NULL, exit_pred);
- BB_COPY_PARTITION (bb, e->src);
- rtx_insn *ret = targetm.gen_simple_return ();
- rtx_jump_insn *start = emit_jump_insn_after (ret, BB_END (bb));
- JUMP_LABEL (start) = simple_return_rtx;
- emit_barrier_after (start);
-
- *pdest_bb = bb;
- make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
- }
- redirect_edge_and_branch_force (e, *pdest_bb);
- }
- unconverted_simple_returns.release ();
- }
-
- if (entry_edge != orig_entry_edge)
- {
- FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
- if (EDGE_COUNT (e->src->preds) != 0
- && (e->flags & EDGE_FAKE) != 0
- && !bitmap_bit_p (&bb_flags, e->src->index))
- {
- e = fix_fake_fallthrough_edge (e);
-
- emit_return_into_block (true, e->src);
- e->flags &= ~(EDGE_FALLTHRU | EDGE_FAKE);
- }
- }
-}