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);
+     }
  
    /* Identify the path.  */
    nrem = find_path (e, &rem_bbs);

Reply via email to