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)

Reply via email to