On Wed, Jan 4, 2012 at 2:01 PM, Jan Hubicka <hubi...@ucw.cz> wrote: > Hi, > in the testcase bellow the loop peeling simplifies exit condition in a way > that the outer loop is destroyed. After some discussion with Zdenek I learnt > that remove_path is then supposed to destroy the outer loop by calling unloop > on it, but there is thinko in the function assuming that just the immediately > outer loop can be eliminated. This is not true in this case: inner loop > has two exists, one closing outer loop and the ohter closing outer loop of the > outer loop. Outer loop stays, but outer loop of outer loop needs to be > removed, > so we need to walk the whole hiarchy upwards. > > Bootstrapped/regtested x86_64-linux, OK? > > Honza > > int a, b, c, d; > > static void > foo (int *x) > { > c = 0; > while (1) > { > if (*x) > break; > while (b) > for (; c; c = 0); > for (d = 18; d != 18; d++) > if (c) > { > foo (x); > return; > } > } > } > > static void > bar () > { > foo (0); > foo (0); > for (;;) > ; > } > > baz () > { > for (; a;) > bar (); > } > PR middle-end/49710 > * cfgloopmanip.c (remove_path): Walk loop hiearchy upwards when > unlooping loops. > Index: cfgloopmanip.c > =================================================================== > *** cfgloopmanip.c (revision 182871) > --- cfgloopmanip.c (working copy) > *************** remove_path (edge e) > *** 291,296 **** > --- 291,297 ---- > sbitmap seen; > bool irred_invalidated = false; > edge_iterator ei; > + struct loop *l; > > if (!can_remove_branch_p (e)) > return false; > *************** remove_path (edge e) > *** 315,323 **** > 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)) > unloop (e->src->loop_father, &irred_invalidated); > > /* Identify the path. */ > nrem = find_path (e, &rem_bbs); > --- 316,333 ---- > 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)) > 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); > + }
It must be possible to merge the two loops, no? And it asks for a comment. > /* Identify the path. */ > nrem = find_path (e, &rem_bbs);