For easier reviewing, I have attached the diff to the cfgcleanup
version previous to the patch backout.
I'm not sure what the best way to keep the svn history sane is. When/if
the patch is approved, should I first do an
svn merge -r108792:108791, check that in, and then apply the patch with
the actual new stuff?
Or will an svn copy of cfgcleanup.c work better?
Index: cfgcleanup.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L cfgcleanup.c (revision 108713) -L
cfgcleanup.c (working copy) .svn/tmp/text-base/cfgcleanup.c.svn-base
cfgcleanup.c
--- cfgcleanup.c (revision 108713)
+++ cfgcleanup.c (working copy)
@@ -936,8 +936,8 @@ condjump_equiv_p (struct equiv_info *inf
if (code2 == UNKNOWN)
return false;
- if (call_init && !struct_equiv_init (STRUCT_EQUIV_START | info->mode, info))
- gcc_unreachable ();
+ if (call_init)
+ struct_equiv_init (STRUCT_EQUIV_START | info->mode, info, false);
/* 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
@@ -1096,7 +1096,7 @@ outgoing_edges_match (int *mode, struct
}
if (identical
- && struct_equiv_init (STRUCT_EQUIV_START | *mode, info))
+ && struct_equiv_init (STRUCT_EQUIV_START | *mode, info, true))
{
bool match;
@@ -1118,17 +1118,20 @@ outgoing_edges_match (int *mode, struct
}
}
+ /* Ensure that the edge counts do match. */
+ if (EDGE_COUNT (bb1->succs) != EDGE_COUNT (bb2->succs))
+ return false;
+
/* First ensure that the instructions match. There may be many outgoing
edges so this test is generally cheaper. */
- if (!struct_equiv_init (STRUCT_EQUIV_START | *mode, info)
+ /* FIXME: the regset compare might be costly. We should try to get a cheap
+ and reasonably effective test first. */
+ if (!struct_equiv_init (STRUCT_EQUIV_START | *mode, info, true)
|| !insns_match_p (BB_END (bb1), BB_END (bb2), info))
return false;
- /* Search the outgoing edges, ensure that the counts do match, find possible
- fallthru and exception handling edges since these needs more
- validation. */
- if (EDGE_COUNT (bb1->succs) != EDGE_COUNT (bb2->succs))
- return false;
+ /* Search the outgoing edges, find possible fallthru and exception
+ handling edges since these needs more validation. */
FOR_EACH_EDGE (e1, ei, bb1->succs)
{
@@ -1353,8 +1356,6 @@ try_crossjump_to_edge (int mode, edge e1
fprintf (dump_file, "Splitting bb %i before %i insns\n",
src2->index, nmatch);
redirect_to = split_block (src2, PREV_INSN (info.cur.x_start))->dest;
- COPY_REG_SET (info.y_block->il.rtl->global_live_at_end,
- info.x_block->il.rtl->global_live_at_end);
}
if (dump_file)
@@ -1432,6 +1433,8 @@ try_crossjump_to_edge (int mode, edge e1
to_remove = single_succ (redirect_from);
redirect_edge_and_branch_force (single_succ_edge (redirect_from),
redirect_to);
+ COPY_REG_SET (redirect_from->il.rtl->global_live_at_end,
+ redirect_to->il.rtl->global_live_at_start);
delete_basic_block (to_remove);
update_forwarder_flag (redirect_from);
@@ -1588,9 +1591,22 @@ try_optimize_cfg (int mode)
bool changed;
int iterations = 0;
basic_block bb, b, next;
+ bool can_modify_jumps = ! targetm.cannot_modify_jumps_p ();
+ bool do_crossjump = false;
- if (mode & CLEANUP_CROSSJUMP)
- add_noreturn_fake_exit_edges ();
+ if (can_modify_jumps && (mode & CLEANUP_CROSSJUMP))
+ {
+ do_crossjump = true;
+ /* Life info updates malfunction in the presence of fake edges.
+ If we want to do any updates while fake edges are present, we'll have
+ to make sure to exclude them when recomputing global_live_at_end,
+ or treat them like EH edges. */
+ update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
+ (PROP_DEATH_NOTES
+ | ((mode & CLEANUP_POST_REGSTACK)
+ ? PROP_POST_REGSTACK : 0)));
+ add_noreturn_fake_exit_edges ();
+ }
if (mode & (CLEANUP_UPDATE_LIFE | CLEANUP_CROSSJUMP | CLEANUP_THREADING))
clear_bb_flags ();
@@ -1598,7 +1614,7 @@ try_optimize_cfg (int mode)
FOR_EACH_BB (bb)
update_forwarder_flag (bb);
- if (! targetm.cannot_modify_jumps_p ())
+ if (can_modify_jumps)
{
first_pass = true;
/* Attempt to merge blocks as made possible by edge removal. If
@@ -1754,8 +1770,8 @@ try_optimize_cfg (int mode)
changed_here = true;
/* Look for shared code between blocks. */
- if ((mode & CLEANUP_CROSSJUMP)
- && try_crossjump_bb (mode, b))
+ if (do_crossjump
+ && try_crossjump_bb (mode | STRUCT_EQUIV_SUSPEND_UPDATES, b))
changed_here = true;
/* Don't get confused by the index shift caused by
@@ -1766,8 +1782,9 @@ try_optimize_cfg (int mode)
changed = true;
}
- if ((mode & CLEANUP_CROSSJUMP)
- && try_crossjump_bb (mode, EXIT_BLOCK_PTR))
+ if (do_crossjump
+ && try_crossjump_bb (mode | STRUCT_EQUIV_SUSPEND_UPDATES,
+ EXIT_BLOCK_PTR))
changed = true;
#ifdef ENABLE_CHECKING
@@ -1781,7 +1798,7 @@ try_optimize_cfg (int mode)
while (changed);
}
- if (mode & CLEANUP_CROSSJUMP)
+ if (do_crossjump)
remove_fake_exit_edges ();
FOR_ALL_BB (b)