aboutsummaryrefslogtreecommitdiff
path: root/gcc/cfgcleanup.c
diff options
context:
space:
mode:
authorH.J. Lu <hongjiu.lu@intel.com>2010-11-03 17:07:04 +0000
committerH.J. Lu <hongjiu.lu@intel.com>2010-11-03 17:07:04 +0000
commitf89ff9b048252f0bef5e4ffee3b098c9e8fe21c7 (patch)
tree7a4e03609ddc7a9995461dfe806444aef488da4c /gcc/cfgcleanup.c
parentbeef6597aeca460cb80850a1fc676a224b009690 (diff)
Revert revision 164552.
gcc/ 2010-11-03 H.J. Lu <hongjiu.lu@intel.com> PR rtl-optimization/45865 * Makefile.in (df-problems.o): Revert revision 164552. * basic-block.h (enum bb_flags): Likewise. * cfgcleanup.c (block_was_dirty): Likewise. (try_forward_edges): Likewise. (try_crossjump_bb): Likewise. (try_head_merge_bb): Likewise. (try_optimize_cfg): Likewise. (cleanup_cfg): Likewise. * df-core.c (df_set_bb_dirty): Likewise. * df-problems.c: Likewise. (df_simulate_find_uses): Likewise. (MEMREF_NORMAL, MEMREF_VOLATILE): Likewise. (find_memory, find_memory_store): Likewise. (can_move_insns_across): Likewise. * df.h (can_move_insns_across): Likewise. * ifcvt.c (find_memory): Likewise. (dead_or_predicable): Likewise. gcc/testsuite/ 2010-11-03 H.J. Lu <hongjiu.lu@intel.com> PR rtl-optimization/45865 * gcc.dg/pr45865.c: New. * gcc.dg/torture/pr45865.c: Likewise. * gcc.target/arm/headmerge-1.c: Revert revision 164552. * gcc.target/arm/headmerge-2.c: Likewise. * gcc.target/i386/headmerge-1.c: Likewise. * gcc.target/i386/headmerge-2.c: Likewise. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@166259 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cfgcleanup.c')
-rw-r--r--gcc/cfgcleanup.c317
1 files changed, 8 insertions, 309 deletions
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index 881a4f34d18..dc41f45bd6d 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -66,10 +66,6 @@ static bool first_pass;
/* Set to true if crossjumps occured in the latest run of try_optimize_cfg. */
static bool crossjumps_occured;
-/* Set to true if we couldn't run an optimization due to stale liveness
- information; we should run df_analyze to enable more opportunities. */
-static bool block_was_dirty;
-
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);
@@ -436,7 +432,7 @@ try_forward_edges (int mode, basic_block b)
int counter, goto_locus;
bool threaded = false;
int nthreaded_edges = 0;
- bool may_thread = first_pass || (b->flags & BB_MODIFIED) != 0;
+ bool may_thread = first_pass | df_get_bb_dirty (b);
/* Skip complex edges because we don't know how to update them.
@@ -471,7 +467,7 @@ try_forward_edges (int mode, basic_block b)
{
basic_block new_target = NULL;
bool new_target_threaded = false;
- may_thread |= (target->flags & BB_MODIFIED) != 0;
+ may_thread |= df_get_bb_dirty (target);
if (FORWARDER_BLOCK_P (target)
&& !(single_succ_edge (target)->flags & EDGE_CROSSING)
@@ -1855,8 +1851,8 @@ try_crossjump_bb (int mode, basic_block bb)
/* If nothing changed since the last attempt, there is nothing
we can do. */
if (!first_pass
- && !((e->src->flags & BB_MODIFIED)
- || (fallthru->src->flags & BB_MODIFIED)))
+ && (!(df_get_bb_dirty (e->src))
+ && !(df_get_bb_dirty (fallthru->src))))
continue;
if (try_crossjump_to_edge (mode, e, fallthru))
@@ -1905,8 +1901,8 @@ try_crossjump_bb (int mode, basic_block bb)
/* If nothing changed since the last attempt, there is nothing
we can do. */
if (!first_pass
- && !((e->src->flags & BB_MODIFIED)
- || (e2->src->flags & BB_MODIFIED)))
+ && (!(df_get_bb_dirty (e->src))
+ && !(df_get_bb_dirty (e2->src))))
continue;
if (try_crossjump_to_edge (mode, e, e2))
@@ -1925,289 +1921,6 @@ try_crossjump_bb (int mode, basic_block bb)
return changed;
}
-/* Search the successors of BB for common insn sequences. When found,
- share code between them by moving it across the basic block
- boundary. Return true if any changes made. */
-
-static bool
-try_head_merge_bb (basic_block bb)
-{
- basic_block final_dest_bb = NULL;
- int max_match = INT_MAX;
- edge e0;
- rtx *headptr, *currptr, *nextptr;
- bool changed, moveall;
- unsigned ix;
- rtx e0_last_head, cond, move_before;
- unsigned nedges = EDGE_COUNT (bb->succs);
- rtx jump = BB_END (bb);
- regset live, live_union;
-
- /* Nothing to do if there is not at least two outgoing edges. */
- if (nedges < 2)
- return false;
-
- /* Don't crossjump if this block ends in a computed jump,
- unless we are optimizing for size. */
- if (optimize_bb_for_size_p (bb)
- && bb != EXIT_BLOCK_PTR
- && computed_jump_p (BB_END (bb)))
- return false;
-
- cond = get_condition (jump, &move_before, true, false);
- if (cond == NULL_RTX)
- move_before = jump;
-
- for (ix = 0; ix < nedges; ix++)
- if (EDGE_SUCC (bb, ix)->dest == EXIT_BLOCK_PTR)
- return false;
-
- for (ix = 0; ix < nedges; ix++)
- {
- edge e = EDGE_SUCC (bb, ix);
- basic_block other_bb = e->dest;
-
- if (df_get_bb_dirty (other_bb))
- {
- block_was_dirty = true;
- return false;
- }
-
- if (e->flags & EDGE_ABNORMAL)
- return false;
-
- /* Normally, all destination blocks must only be reachable from this
- block, i.e. they must have one incoming edge.
-
- There is one special case we can handle, that of multiple consecutive
- jumps where the first jumps to one of the targets of the second jump.
- This happens frequently in switch statements for default labels.
- The structure is as follows:
- FINAL_DEST_BB
- ....
- if (cond) jump A;
- fall through
- BB
- jump with targets A, B, C, D...
- A
- has two incoming edges, from FINAL_DEST_BB and BB
-
- In this case, we can try to move the insns through BB and into
- FINAL_DEST_BB. */
- if (EDGE_COUNT (other_bb->preds) != 1)
- {
- edge incoming_edge, incoming_bb_other_edge;
- edge_iterator ei;
-
- if (final_dest_bb != NULL
- || EDGE_COUNT (other_bb->preds) != 2)
- return false;
-
- /* We must be able to move the insns across the whole block. */
- move_before = BB_HEAD (bb);
- while (!NONDEBUG_INSN_P (move_before))
- move_before = NEXT_INSN (move_before);
-
- if (EDGE_COUNT (bb->preds) != 1)
- return false;
- incoming_edge = EDGE_PRED (bb, 0);
- final_dest_bb = incoming_edge->src;
- if (EDGE_COUNT (final_dest_bb->succs) != 2)
- return false;
- FOR_EACH_EDGE (incoming_bb_other_edge, ei, final_dest_bb->succs)
- if (incoming_bb_other_edge != incoming_edge)
- break;
- if (incoming_bb_other_edge->dest != other_bb)
- return false;
- }
- }
-
- e0 = EDGE_SUCC (bb, 0);
- e0_last_head = NULL_RTX;
- changed = false;
-
- for (ix = 1; ix < nedges; ix++)
- {
- edge e = EDGE_SUCC (bb, ix);
- rtx e0_last, e_last;
- int nmatch;
-
- nmatch = flow_find_head_matching_sequence (e0->dest, e->dest,
- &e0_last, &e_last, 0);
- if (nmatch == 0)
- return false;
-
- if (nmatch < max_match)
- {
- max_match = nmatch;
- e0_last_head = e0_last;
- }
- }
-
- /* If we matched an entire block, we probably have to avoid moving the
- last insn. */
- if (max_match > 0
- && e0_last_head == BB_END (e0->dest)
- && (find_reg_note (e0_last_head, REG_EH_REGION, 0)
- || control_flow_insn_p (e0_last_head)))
- {
- max_match--;
- if (max_match == 0)
- return false;
- do
- e0_last_head = prev_real_insn (e0_last_head);
- while (DEBUG_INSN_P (e0_last_head));
- }
-
- if (max_match == 0)
- return false;
-
- /* We must find a union of the live registers at each of the end points. */
- live = BITMAP_ALLOC (NULL);
- live_union = BITMAP_ALLOC (NULL);
-
- currptr = XNEWVEC (rtx, nedges);
- headptr = XNEWVEC (rtx, nedges);
- nextptr = XNEWVEC (rtx, nedges);
-
- for (ix = 0; ix < nedges; ix++)
- {
- int j;
- basic_block merge_bb = EDGE_SUCC (bb, ix)->dest;
- rtx head = BB_HEAD (merge_bb);
-
- while (!NONDEBUG_INSN_P (head))
- head = NEXT_INSN (head);
- headptr[ix] = head;
- currptr[ix] = head;
-
- /* Compute the end point and live information */
- for (j = 1; j < max_match; j++)
- do
- head = NEXT_INSN (head);
- while (!NONDEBUG_INSN_P (head));
- simulate_backwards_to_point (merge_bb, live, head);
- IOR_REG_SET (live_union, live);
- }
-
- /* If we're moving across two blocks, verify the validity of the
- first move, then adjust the target and let the loop below deal
- with the final move. */
- if (final_dest_bb != NULL)
- {
- rtx move_upto;
-
- moveall = can_move_insns_across (currptr[0], e0_last_head, move_before,
- jump, e0->dest, live_union,
- NULL, &move_upto);
- if (!moveall)
- e0_last_head = move_upto;
- if (e0_last_head == NULL_RTX)
- goto out;
-
- jump = BB_END (final_dest_bb);
- cond = get_condition (jump, &move_before, true, false);
- if (cond == NULL_RTX)
- move_before = jump;
- }
-
- do
- {
- rtx move_upto;
- moveall = can_move_insns_across (currptr[0], e0_last_head,
- move_before, jump, e0->dest, live_union,
- NULL, &move_upto);
- if (!moveall && move_upto == NULL_RTX)
- {
- if (jump == move_before)
- break;
-
- /* Try again, using a different insertion point. */
- move_before = jump;
-
-#ifdef HAVE_cc0
- /* Don't try moving before a cc0 user, as that may invalidate
- the cc0. */
- if (reg_mentioned_p (cc0_rtx, jump))
- break;
-#endif
-
- continue;
- }
-
- if (final_dest_bb && !moveall)
- /* We haven't checked whether a partial move would be OK for the first
- move, so we have to fail this case. */
- break;
-
- changed = true;
- for (;;)
- {
- if (currptr[0] == move_upto)
- break;
- for (ix = 0; ix < nedges; ix++)
- {
- rtx curr = currptr[ix];
- do
- curr = NEXT_INSN (curr);
- while (!NONDEBUG_INSN_P (curr));
- currptr[ix] = curr;
- }
- }
-
- /* If we can't currently move all of the identical insns, remember
- each insn after the range that we'll merge. */
- if (!moveall)
- for (ix = 0; ix < nedges; ix++)
- {
- rtx curr = currptr[ix];
- do
- curr = NEXT_INSN (curr);
- while (!NONDEBUG_INSN_P (curr));
- nextptr[ix] = curr;
- }
-
- reorder_insns (headptr[0], currptr[0], PREV_INSN (move_before));
- df_set_bb_dirty (EDGE_SUCC (bb, 0)->dest);
- if (final_dest_bb != NULL)
- df_set_bb_dirty (final_dest_bb);
- df_set_bb_dirty (bb);
- for (ix = 1; ix < nedges; ix++)
- {
- df_set_bb_dirty (EDGE_SUCC (bb, ix)->dest);
- delete_insn_chain (headptr[ix], currptr[ix], false);
- }
- if (!moveall)
- {
- if (jump == move_before)
- break;
-
- /* For the unmerged insns, try a different insertion point. */
- move_before = jump;
-
-#ifdef HAVE_cc0
- /* Don't try moving before a cc0 user, as that may invalidate
- the cc0. */
- if (reg_mentioned_p (cc0_rtx, jump))
- break;
-#endif
-
- for (ix = 0; ix < nedges; ix++)
- currptr[ix] = headptr[ix] = nextptr[ix];
- }
- }
- while (!moveall);
-
- out:
- free (currptr);
- free (headptr);
- free (nextptr);
-
- crossjumps_occured |= changed;
-
- return changed;
-}
-
/* Return true if BB contains just bb note, or bb note followed
by only DEBUG_INSNs. */
@@ -2253,7 +1966,6 @@ try_optimize_cfg (int mode)
one predecessor, they may be combined. */
do
{
- block_was_dirty = false;
changed = false;
iterations++;
@@ -2453,13 +2165,6 @@ try_optimize_cfg (int mode)
&& try_crossjump_bb (mode, b))
changed_here = true;
- if ((mode & CLEANUP_CROSSJUMP)
- /* This can lengthen register lifetimes. Do it only after
- reload. */
- && reload_completed
- && try_head_merge_bb (b))
- changed_here = true;
-
/* Don't get confused by the index shift caused by
deleting blocks. */
if (!changed_here)
@@ -2472,13 +2177,6 @@ try_optimize_cfg (int mode)
&& try_crossjump_bb (mode, EXIT_BLOCK_PTR))
changed = true;
- if (block_was_dirty)
- {
- /* This should only be set by head-merging. */
- gcc_assert (mode & CLEANUP_CROSSJUMP);
- df_analyze ();
- }
-
#ifdef ENABLE_CHECKING
if (changed)
verify_flow_info ();
@@ -2663,7 +2361,8 @@ cleanup_cfg (int mode)
if ((mode & CLEANUP_EXPENSIVE) && !reload_completed
&& !delete_trivially_dead_insns (get_insns (), max_reg_num ()))
break;
- if ((mode & CLEANUP_CROSSJUMP) && crossjumps_occured)
+ else if ((mode & CLEANUP_CROSSJUMP)
+ && crossjumps_occured)
run_fast_dce ();
}
else