This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH]: Don't remove fake edges in purge_dead_edges


Someone noticed this with an optimization they are working on that
improves RTL GCSE (AFAIK, it could trigger in the right set of
conditions, but nobody seems to hit it)

What happens is this:


1. We insert fake exit edges for the noreturn calls at the start of
GCSE.

2. His insertions cause us to decide to run purge_dead_edges, which is
perfectly fine.

3. Purge_dead_edges removes *all* the edges from the noreturn block,
include the fake ones, because it gets to this loop at the bottom:


  for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
    {
      if (!(e->flags & EDGE_FALLTHRU))
        {
          bb->flags |= BB_DIRTY;
          remove_edge (e);
          purged = true;
        }
      else
        ei_next (&ei);
    }



Of course, in this case, *none* of the edges are fallthru.


4. purge_dead_edges then aborts because the noreturn block has no
successors (since it just removed the only edge :P).


The following fixes it by not removing fake edges in purge_dead_edges.
Bootstrapped and regtested on i686-pc-linux-gnu.

Okay for mainline?

2005-05-17  Daniel Berlin  <dberlin@dberlin.org>

	* cfgrtl.c (purge_dead_edges): Don't remove fake edges.

Index: cfgrtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgrtl.c,v
retrieving revision 1.171
diff -u -p -r1.171 cfgrtl.c
--- cfgrtl.c	25 Apr 2005 12:46:05 -0000	1.171
+++ cfgrtl.c	17 May 2005 13:51:31 -0000
@@ -2428,9 +2429,12 @@ purge_dead_edges (basic_block bb)
   if (!found)
     return purged;
 
+  /* Remove all but the fake and fallthru edges.  The fake edge may be
+     the only successor for this block in the case of noreturn
+     calls.  */
   for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
     {
-      if (!(e->flags & EDGE_FALLTHRU))
+      if (!(e->flags & (EDGE_FALLTHRU | EDGE_FAKE)))
 	{
 	  bb->flags |= BB_DIRTY;
 	  remove_edge (e);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]