http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49710

--- Comment #6 from Jan Hubicka <hubicka at gcc dot gnu.org> 2012-01-03 
17:52:04 UTC ---
Hi,
after some discussion with Zdenek, it seems that the problem is wrong
assumption in remove_path that the only loops removed are at the top of loop
hiearchy.  It is not true here, since innermost loops has two exits, one to
outer loop and one to the outer loop of outer loop.  Only second exit gets
removed and thus outer loop stays but outer loop of the outer loop should be
unlooped.

I am testing the attached patch.

Honza

Index: cfgloopmanip.c
===================================================================
--- cfgloopmanip.c      (revision 182853)
+++ cfgloopmanip.c      (working copy)
@@ -291,6 +291,7 @@ remove_path (edge e)
   sbitmap seen;
   bool irred_invalidated = false;
   edge_iterator ei;
+  struct loop *l;

   if (!can_remove_branch_p (e))
     return false;
@@ -315,9 +316,18 @@ remove_path (edge e)
      normally.   We may assume that e->dest is not a header of any loop,
      as it now has exactly one predecessor.  */
   while (loop_outer (e->src->loop_father)
-        && dominated_by_p (CDI_DOMINATORS,
-                           e->src->loop_father->latch, e->dest))
+        && dominated_by_p (CDI_DOMINATORS,
+                           e->src->loop_father->latch, e->dest))
     unloop (e->src->loop_father, &irred_invalidated);
+  l = e->src->loop_father;
+  while (l && loop_outer (l))
+    {
+      while (loop_outer (loop_outer (l))
+            && dominated_by_p (CDI_DOMINATORS,
+                               loop_outer (l)->latch, e->dest))
+        unloop (loop_outer (l), &irred_invalidated);
+      l = loop_outer (l);
+    }

   /* Identify the path.  */
   nrem = find_path (e, &rem_bbs);

Reply via email to