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);