/* Control flow optimization code for GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
This file is part of GCC.
#include "expr.h"
#define FORWARDER_BLOCK_P(BB) ((BB)->flags & BB_FORWARDER_BLOCK)
-
+
/* Set to true when we are running first pass of try_optimize_cfg loop. */
static bool first_pass;
static bool try_crossjump_to_edge (int, edge, edge);
static bool try_crossjump_bb (int, basic_block);
static bool outgoing_edges_match (int, basic_block, basic_block);
static int flow_find_cross_jump (int, basic_block, basic_block, rtx *, rtx *);
-static bool insns_match_p (int, rtx, rtx);
+static bool old_insns_match_p (int, rtx, rtx);
static void merge_blocks_move_predecessor_nojumps (basic_block, basic_block);
static void merge_blocks_move_successor_nojumps (basic_block, basic_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
- must be left untouched (they are required to make it safely across
- partition boundaries). See the comments at the top of
+ 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 (BB_PARTITION (jump_block) != BB_PARTITION (jump_dest_block)
switch (GET_CODE (exp))
{
/* In case we do clobber the register, mark it as equal, as we know the
- value is dead so it don't have to match. */
+ value is dead so it don't have to match. */
case CLOBBER:
if (REG_P (XEXP (exp, 0)))
{
/* 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
+ 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 (find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX))
/* Skip complex edges because we don't know how to update them.
- Still handle fallthru edges, as we can succeed to forward fallthru
- edge to the same place as the branch edge of conditional branch
- and turn conditional branch to an unconditional branch. */
+ Still handle fallthru edges, as we can succeed to forward fallthru
+ edge to the same place as the branch edge of conditional branch
+ and turn conditional branch to an unconditional branch. */
if (e->flags & EDGE_COMPLEX)
{
ei_next (&ei);
}
target = first = e->dest;
- counter = 0;
+ counter = NUM_FIXED_BLOCKS;
/* If we are partitioning hot/cold basic_blocks, we don't want to mess
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
+ 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. */
may_thread |= target->flags & BB_DIRTY;
if (FORWARDER_BLOCK_P (target)
- && !(single_succ_edge (target)->flags & EDGE_CROSSING)
+ && !(single_succ_edge (target)->flags & EDGE_CROSSING)
&& single_succ (target) != EXIT_BLOCK_PTR)
{
/* Bypass trivial infinite loops. */
if (t)
{
if (!threaded_edges)
- threaded_edges = xmalloc (sizeof (*threaded_edges)
- * n_basic_blocks);
+ threaded_edges = XNEWVEC (edge, n_basic_blocks);
else
{
int i;
if (t->dest == b)
break;
- gcc_assert (nthreaded_edges < n_basic_blocks);
+ gcc_assert (nthreaded_edges < n_basic_blocks - NUM_FIXED_BLOCKS);
threaded_edges[nthreaded_edges++] = t;
new_target = t->dest;
if (!new_target)
break;
- /* Avoid killing of loop pre-headers, as it is the place loop
- optimizer wants to hoist code to.
-
- For fallthru forwarders, the LOOP_BEG note must appear between
- the header of block and CODE_LABEL of the loop, for non forwarders
- it must appear before the JUMP_INSN. */
- if ((mode & CLEANUP_PRE_LOOP) && optimize && flag_loop_optimize)
- {
- rtx insn = (EDGE_SUCC (target, 0)->flags & EDGE_FALLTHRU
- ? BB_HEAD (target) : prev_nonnote_insn (BB_END (target)));
-
- if (!NOTE_P (insn))
- insn = NEXT_INSN (insn);
-
- for (; insn && !LABEL_P (insn) && !INSN_P (insn);
- insn = NEXT_INSN (insn))
- if (NOTE_P (insn)
- && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
- break;
-
- if (insn && NOTE_P (insn))
- break;
-
- /* Do not clean up branches to just past the end of a loop
- at this time; it can mess up the loop optimizer's
- recognition of some patterns. */
-
- insn = PREV_INSN (BB_HEAD (target));
- if (insn && NOTE_P (insn)
- && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
- break;
- }
-
counter++;
target = new_target;
threaded |= new_target_threaded;
/* 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.
-
+
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
+ 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 (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
+ 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 (BB_PARTITION (a) != BB_PARTITION (b))
necessary. */
only_notes = squeeze_notes (&BB_HEAD (b), &BB_END (b));
gcc_assert (!only_notes);
-
+
/* Scramble the insn chain. */
reorder_insns_nobb (BB_HEAD (b), BB_END (b), BB_END (a));
/* 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
+ 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 (BB_PARTITION (b) != BB_PARTITION (c))
return NULL;
-
-
/* If B has a fallthru edge to C, no need to move anything. */
if (e->flags & EDGE_FALLTHRU)
edge_iterator ei;
/* Avoid overactive code motion, as the forwarder blocks should be
- eliminated by edge redirection instead. One exception might have
+ eliminated by edge redirection instead. One exception might have
been if B is a forwarder block and C has no fallthru edge, but
that should be cleaned up by bb-reorder instead. */
if (FORWARDER_BLOCK_P (b) || FORWARDER_BLOCK_P (c))
if (! c_has_outgoing_fallthru)
{
merge_blocks_move_successor_nojumps (b, c);
- return next == ENTRY_BLOCK_PTR ? next->next_bb : next;
+ return next == ENTRY_BLOCK_PTR ? next->next_bb : next;
}
/* If B does not have an incoming fallthru, then it can be moved
MEM_ATTRS (y) = 0;
else if (! MEM_ATTRS (y))
MEM_ATTRS (x) = 0;
- else
+ else
{
rtx mem_size;
set_mem_alias_set (x, 0);
set_mem_alias_set (y, 0);
}
-
+
if (! mem_expr_equal_p (MEM_EXPR (x), MEM_EXPR (y)))
{
set_mem_expr (x, 0);
set_mem_offset (x, 0);
set_mem_offset (y, 0);
}
-
+
if (!MEM_SIZE (x))
mem_size = NULL_RTX;
else if (!MEM_SIZE (y))
set_mem_align (y, MEM_ALIGN (x));
}
}
-
+
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
/* Return true if I1 and I2 are equivalent and thus can be crossjumped. */
static bool
-insns_match_p (int mode ATTRIBUTE_UNUSED, rtx i1, rtx i2)
+old_insns_match_p (int mode ATTRIBUTE_UNUSED, rtx i1, rtx i2)
{
rtx p1, p2;
if (CALL_P (i1)
&& (!rtx_equal_p (CALL_INSN_FUNCTION_USAGE (i1),
- CALL_INSN_FUNCTION_USAGE (i2))
+ CALL_INSN_FUNCTION_USAGE (i2))
|| SIBLING_CALL_P (i1) != SIBLING_CALL_P (i2)))
return false;
if ((mode & CLEANUP_POST_REGSTACK) && stack_regs_mentioned (i1))
{
/* If register stack conversion has already been done, then
- death notes must also be compared before it is certain that
- the two instruction streams match. */
+ death notes must also be compared before it is certain that
+ the two instruction streams match. */
rtx note;
HARD_REG_SET i1_regset, i2_regset;
if (i1 == BB_HEAD (bb1) || i2 == BB_HEAD (bb2))
break;
- if (!insns_match_p (mode, i1, i2))
+ if (!old_insns_match_p (mode, i1, i2))
break;
merge_memattrs (i1, i2);
return ninsns;
}
+/* Return true iff the condbranches at the end of BB1 and BB2 match. */
+bool
+condjump_equiv_p (struct equiv_info *info, bool call_init)
+{
+ basic_block bb1 = info->x_block;
+ basic_block bb2 = info->y_block;
+ edge b1 = BRANCH_EDGE (bb1);
+ edge b2 = BRANCH_EDGE (bb2);
+ edge f1 = FALLTHRU_EDGE (bb1);
+ edge f2 = FALLTHRU_EDGE (bb2);
+ bool reverse, match;
+ rtx set1, set2, cond1, cond2;
+ rtx src1, src2;
+ enum rtx_code code1, code2;
+
+ /* Get around possible forwarders on fallthru edges. Other cases
+ should be optimized out already. */
+ if (FORWARDER_BLOCK_P (f1->dest))
+ f1 = single_succ_edge (f1->dest);
+
+ if (FORWARDER_BLOCK_P (f2->dest))
+ f2 = single_succ_edge (f2->dest);
+
+ /* To simplify use of this function, return false if there are
+ unneeded forwarder blocks. These will get eliminated later
+ during cleanup_cfg. */
+ if (FORWARDER_BLOCK_P (f1->dest)
+ || FORWARDER_BLOCK_P (f2->dest)
+ || FORWARDER_BLOCK_P (b1->dest)
+ || FORWARDER_BLOCK_P (b2->dest))
+ return false;
+
+ if (f1->dest == f2->dest && b1->dest == b2->dest)
+ reverse = false;
+ else if (f1->dest == b2->dest && b1->dest == f2->dest)
+ reverse = true;
+ else
+ return false;
+
+ set1 = pc_set (BB_END (bb1));
+ set2 = pc_set (BB_END (bb2));
+ if ((XEXP (SET_SRC (set1), 1) == pc_rtx)
+ != (XEXP (SET_SRC (set2), 1) == pc_rtx))
+ reverse = !reverse;
+
+ src1 = SET_SRC (set1);
+ src2 = SET_SRC (set2);
+ cond1 = XEXP (src1, 0);
+ cond2 = XEXP (src2, 0);
+ code1 = GET_CODE (cond1);
+ if (reverse)
+ code2 = reversed_comparison_code (cond2, BB_END (bb2));
+ else
+ code2 = GET_CODE (cond2);
+
+ if (code2 == UNKNOWN)
+ return false;
+
+ if (call_init && !struct_equiv_init (STRUCT_EQUIV_START | info->mode, info))
+ gcc_unreachable ();
+ /* Make the sources of the pc sets unreadable so that when we call
+ insns_match_p it won't process them.
+ The death_notes_match_p from insns_match_p won't see the local registers
+ used for the pc set, but that could only cause missed optimizations when
+ there are actually condjumps that use stack registers. */
+ SET_SRC (set1) = pc_rtx;
+ SET_SRC (set2) = pc_rtx;
+ /* Verify codes and operands match. */
+ if (code1 == code2)
+ {
+ match = (insns_match_p (BB_END (bb1), BB_END (bb2), info)
+ && rtx_equiv_p (&XEXP (cond1, 0), XEXP (cond2, 0), 1, info)
+ && rtx_equiv_p (&XEXP (cond1, 1), XEXP (cond2, 1), 1, info));
+
+ }
+ else if (code1 == swap_condition (code2))
+ {
+ match = (insns_match_p (BB_END (bb1), BB_END (bb2), info)
+ && rtx_equiv_p (&XEXP (cond1, 1), XEXP (cond2, 0), 1, info)
+ && rtx_equiv_p (&XEXP (cond1, 0), XEXP (cond2, 1), 1, info));
+
+ }
+ else
+ match = false;
+ SET_SRC (set1) = src1;
+ SET_SRC (set2) = src2;
+ match &= verify_changes (0);
+
+ /* If we return true, we will join the blocks. Which means that
+ we will only have one branch prediction bit to work with. Thus
+ we require the existing branches to have probabilities that are
+ roughly similar. */
+ if (match
+ && !optimize_size
+ && maybe_hot_bb_p (bb1)
+ && maybe_hot_bb_p (bb2))
+ {
+ int prob2;
+
+ if (b1->dest == b2->dest)
+ prob2 = b2->probability;
+ else
+ /* Do not use f2 probability as f2 may be forwarded. */
+ prob2 = REG_BR_PROB_BASE - b2->probability;
+
+ /* Fail if the difference in probabilities is greater than 50%.
+ This rules out two well-predicted branches with opposite
+ outcomes. */
+ if (abs (b1->probability - prob2) > REG_BR_PROB_BASE / 2)
+ {
+ if (dump_file)
+ fprintf (dump_file,
+ "Outcomes of branch in bb %i and %i differ too much (%i %i)\n",
+ bb1->index, bb2->index, b1->probability, prob2);
+
+ match = false;
+ }
+ }
+
+ if (dump_file && match)
+ fprintf (dump_file, "Conditionals in bb %i and %i match.\n",
+ bb1->index, bb2->index);
+
+ if (!match)
+ cancel_changes (0);
+ return match;
+}
+
/* Return true iff outgoing edges of BB1 and BB2 match, together with
the branch instruction. This means that if we commonize the control
flow before end of the basic block, the semantic remains unchanged.
f2 = FALLTHRU_EDGE (bb2);
/* Get around possible forwarders on fallthru edges. Other cases
- should be optimized out already. */
+ should be optimized out already. */
if (FORWARDER_BLOCK_P (f1->dest))
f1 = single_succ_edge (f1->dest);
rr.update_label_nuses = false;
for_each_rtx (&BB_END (bb1), replace_label, &rr);
- match = insns_match_p (mode, BB_END (bb1), BB_END (bb2));
+ match = old_insns_match_p (mode, BB_END (bb1), BB_END (bb2));
if (dump_file && match)
fprintf (dump_file,
"Tablejumps in bb %i and %i match.\n",
/* First ensure that the instructions match. There may be many outgoing
edges so this test is generally cheaper. */
- if (!insns_match_p (mode, BB_END (bb1), BB_END (bb2)))
+ if (!old_insns_match_p (mode, BB_END (bb1), BB_END (bb2)))
return false;
/* Search the outgoing edges, ensure that the counts do match, find possible
FOR_EACH_EDGE (e1, ei, bb1->succs)
{
e2 = EDGE_SUCC (bb2, ei.index);
-
+
if (e1->flags & EDGE_EH)
nehedges1++;
return false;
}
- /* We don't need to match the rest of edges as above checks should be enough
- to ensure that they are equivalent. */
+ /* The same checks as in try_crossjump_to_edge. It is required for RTL
+ version of sequence abstraction. */
+ FOR_EACH_EDGE (e1, ei, bb2->succs)
+ {
+ edge e2;
+ edge_iterator ei;
+ basic_block d1 = e1->dest;
+
+ if (FORWARDER_BLOCK_P (d1))
+ d1 = EDGE_SUCC (d1, 0)->dest;
+
+ FOR_EACH_EDGE (e2, ei, bb1->succs)
+ {
+ basic_block d2 = e2->dest;
+ if (FORWARDER_BLOCK_P (d2))
+ d2 = EDGE_SUCC (d2, 0)->dest;
+ if (d1 == d2)
+ break;
+ }
+
+ if (!e2)
+ return false;
+ }
+
return true;
}
+/* Returns true if BB basic block has a preserve label. */
+
+static bool
+block_has_preserve_label (basic_block bb)
+{
+ return (bb
+ && block_label (bb)
+ && LABEL_PRESERVE_P (block_label (bb)));
+}
+
/* E1 and E2 are edges with the same destination block. Search their
predecessors for common code. If found, redirect control flow from
(maybe the middle of) E1->SRC to (maybe the middle of) E2->SRC. */
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
+ 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)
&& (newpos1 != BB_HEAD (src1)))
return false;
+ /* Avoid deleting preserve label when redirecting ABNORMAL edges. */
+ if (block_has_preserve_label (e1->dest)
+ && (e1->flags & EDGE_ABNORMAL))
+ return false;
+
/* Here we know that the insns in the end of SRC1 which are common with SRC2
will be deleted.
If we have tablejumps in the end of SRC1 and SRC2
redirect_to->count += src1->count;
redirect_to->frequency += src1->frequency;
- /* We may have some registers visible trought the block. */
+ /* We may have some registers visible through the block. */
redirect_to->flags |= BB_DIRTY;
/* Recompute the frequencies and counts of outgoing edges. */
s->count += s2->count;
/* Take care to update possible forwarder blocks. We verified
- that there is no more than one in the chain, so we can't run
- into infinite loop. */
+ that there is no more than one in the chain, so we can't run
+ into infinite loop. */
if (FORWARDER_BLOCK_P (s->dest))
{
single_succ_edge (s->dest)->count += s2->count;
/* 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
+ 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 (BB_PARTITION (EDGE_PRED (bb, 0)->src) !=
- BB_PARTITION (EDGE_PRED (bb, 1)->src)
+ if (BB_PARTITION (EDGE_PRED (bb, 0)->src) !=
+ BB_PARTITION (EDGE_PRED (bb, 1)->src)
|| (EDGE_PRED (bb, 0)->flags & EDGE_CROSSING))
return false;
FOR_EACH_EDGE (e, ei, bb->preds)
{
if (e->flags & EDGE_FALLTHRU)
- fallthru = e;
+ fallthru = e;
}
changed = false;
bool changed_here = false;
/* Delete trivially dead basic blocks. */
- while (EDGE_COUNT (b->preds) == 0)
+ if (EDGE_COUNT (b->preds) == 0)
{
c = b->prev_bb;
if (dump_file)
delete_basic_block (b);
if (!(mode & CLEANUP_CFGLAYOUT))
changed = true;
- b = c;
+ /* Avoid trying to remove ENTRY_BLOCK_PTR. */
+ b = (c == ENTRY_BLOCK_PTR ? c->next_bb : c);
+ continue;
}
/* Remove code labels no longer used. */
reorder_insns_nobb (label, label, bb_note);
BB_HEAD (b) = bb_note;
+ if (BB_END (b) == bb_note)
+ BB_END (b) = label;
}
if (dump_file)
fprintf (dump_file, "Deleted label in block %i.\n",
/* Note that forwarder_block_p true ensures that
there is a successor for this block. */
&& (single_succ_edge (b)->flags & EDGE_FALLTHRU)
- && n_basic_blocks > 1)
+ && n_basic_blocks > NUM_FIXED_BLOCKS + 1)
{
if (dump_file)
fprintf (dump_file,
does not fit merge_blocks interface and is kept here in
hope that it will become useless once more of compiler
is transformed to use cfg_layout mode. */
-
+
if ((mode & CLEANUP_CFGLAYOUT)
&& can_merge_blocks_p (b, c))
{
{
bool changed = false;
+ /* Set the cfglayout mode flag here. We could update all the callers
+ but that is just inconvenient, especially given that we eventually
+ want to have cfglayout mode as the default. */
+ if (current_ir_type () == IR_RTL_CFGLAYOUT)
+ mode |= CLEANUP_CFGLAYOUT;
+
timevar_push (TV_CLEANUP_CFG);
if (delete_unreachable_blocks ())
{
now to introduce more opportunities for try_optimize_cfg. */
if (!(mode & (CLEANUP_NO_INSN_DEL | CLEANUP_UPDATE_LIFE))
&& !reload_completed)
- delete_trivially_dead_insns (get_insns(), max_reg_num ());
+ delete_trivially_dead_insns (get_insns (), max_reg_num ());
}
compact_blocks ();
PROP_DEATH_NOTES
| PROP_SCAN_DEAD_CODE
| PROP_KILL_DEAD_CODE
- | ((mode & CLEANUP_LOG_LINKS)
+ | ((mode & CLEANUP_LOG_LINKS)
? PROP_LOG_LINKS : 0)))
break;
}
&& (mode & CLEANUP_EXPENSIVE)
&& !reload_completed)
{
- if (!delete_trivially_dead_insns (get_insns(), max_reg_num ()))
+ if (!delete_trivially_dead_insns (get_insns (), max_reg_num ()))
break;
}
else
break;
- delete_dead_jumptables ();
+
+ /* Don't call delete_dead_jumptables in cfglayout mode, because
+ that function assumes that jump tables are in the insns stream.
+ But we also don't _have_ to delete dead jumptables in cfglayout
+ mode because we shouldn't even be looking at things that are
+ not in a basic block. Dead jumptables are cleaned up when
+ going out of cfglayout mode. */
+ if (!(mode & CLEANUP_CFGLAYOUT))
+ delete_dead_jumptables ();
}
timevar_pop (TV_CLEANUP_CFG);
return changed;
}
\f
-static void
+static unsigned int
rest_of_handle_jump (void)
{
delete_unreachable_blocks ();
if (cfun->tail_call_emit)
fixup_tail_calls ();
+ return 0;
}
struct tree_opt_pass pass_jump =
{
"sibling", /* name */
- NULL, /* gate */
- rest_of_handle_jump, /* execute */
+ NULL, /* gate */
+ rest_of_handle_jump, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
};
-static void
+static unsigned int
rest_of_handle_jump2 (void)
{
- /* Turn NOTE_INSN_EXPECTED_VALUE into REG_BR_PROB. Do this
- before jump optimization switches branch directions. */
- if (flag_guess_branch_prob)
- expected_value_to_br_prob ();
-
delete_trivially_dead_insns (get_insns (), max_reg_num ());
reg_scan (get_insns (), max_reg_num ());
if (dump_file)
- dump_flow_info (dump_file);
- cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP
- | (flag_thread_jumps ? CLEANUP_THREADING : 0));
-
- create_loop_notes ();
-
- purge_line_number_notes ();
-
- if (optimize)
- cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
-
- /* Jump optimization, and the removal of NULL pointer checks, may
- have reduced the number of instructions substantially. CSE, and
- future passes, allocate arrays whose dimensions involve the
- maximum instruction UID, so if we can reduce the maximum UID
- we'll save big on memory. */
- renumber_insns (dump_file);
+ dump_flow_info (dump_file, dump_flags);
+ cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0)
+ | (flag_thread_jumps ? CLEANUP_THREADING : 0));
+ return 0;
}
struct tree_opt_pass pass_jump2 =
{
"jump", /* name */
- NULL, /* gate */
- rest_of_handle_jump2, /* execute */
+ NULL, /* gate */
+ rest_of_handle_jump2, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */