This fixes PR53695 where we recognize a loop which has only an
abnormal goto edge from its header to its tail.  We already reject
loops during recognition that have at least a single abnormal
predecessor of its head so it seems reasonable to at least require
one regular CFG path from its header to its latch (thus only have
abnormal extra entries / exists).

Not entirely trivial to test as one can see below.

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

Any comments?

Thanks,
Richard.

2012-06-27  Richard Guenther  <rguent...@suse.de>

        PR middle-end/53695
        * cfgloop.c (path_without_edge_flags_1): New function.
        (path_without_edge_flags): Likewise.
        (flow_loops_find): Require at least one regular path from
        loop header to latch.

Index: gcc/cfgloop.c
===================================================================
*** gcc/cfgloop.c       (revision 188987)
--- gcc/cfgloop.c       (working copy)
*************** init_loops_structure (struct loops *loop
*** 365,370 ****
--- 365,424 ----
    loops->tree_root = root;
  }
  
+ /* Return true if there is a path from FROM to the dominated TO where no
+    edge on that path contains FLAGS.  */
+ 
+ static bool
+ path_without_edge_flags_1 (basic_block from, basic_block to, int flags,
+                          bitmap *visited)
+ {
+   while (to != from)
+     {
+       /* At least one such path to the immediate dominator.  */
+       if (single_pred_p (to))
+       {
+         edge e = single_pred_edge (to);
+         if (e->flags & flags)
+           return false;
+         to = e->src;
+       }
+       else
+       {
+         basic_block dom;
+         edge_iterator ei;
+         edge e;
+ 
+         /* We have to guard ourselves to not loop in the face of subloops.  */
+         if (!*visited)
+           *visited = BITMAP_ALLOC (NULL);
+         if (!bitmap_set_bit (*visited, to->index))
+           return false;
+ 
+         dom = get_immediate_dominator (CDI_DOMINATORS, to);
+         FOR_EACH_EDGE(e, ei, to->preds)
+           if (!(e->flags & flags)
+               && (e->src == dom
+                   || path_without_edge_flags_1 (dom, e->src, flags, visited)))
+             break;
+ 
+         to = dom;
+       }
+     }
+ 
+   return true;
+ }
+ 
+ static bool
+ path_without_edge_flags (basic_block from, basic_block to, int flags)
+ {
+   bitmap visited = NULL;
+   bool res;
+   res = path_without_edge_flags_1 (from, to, flags, &visited);
+   if (visited)
+     BITMAP_FREE (visited);
+   return res;
+ }
+ 
  /* Find all the natural loops in the function and save in LOOPS structure and
     recalculate loop_depth information in basic block structures.
     Return the number of natural loops found.  */
*************** flow_loops_find (struct loops *loops)
*** 422,430 ****
             by this block.  A natural loop has a single entry
             node (header) that dominates all the nodes in the
             loop.  It also has single back edge to the header
!            from a latch node.  */
          if (latch != ENTRY_BLOCK_PTR
!             && dominated_by_p (CDI_DOMINATORS, latch, header))
            {
              /* Shared headers should be eliminated by now.  */
              SET_BIT (headers, header->index);
--- 476,488 ----
             by this block.  A natural loop has a single entry
             node (header) that dominates all the nodes in the
             loop.  It also has single back edge to the header
!            from a latch node.
!            If there is no regular path from the header to the
!            latch do not consider this latch (not worth the
!            problems).  */
          if (latch != ENTRY_BLOCK_PTR
!             && dominated_by_p (CDI_DOMINATORS, latch, header)
!             && path_without_edge_flags (header, latch, EDGE_COMPLEX))
            {
              /* Shared headers should be eliminated by now.  */
              SET_BIT (headers, header->index);
*************** verify_loop_structure (void)
*** 1388,1393 ****
--- 1446,1460 ----
              err = 1;
            }
        }
+       else if (loop->latch)
+       {
+         if (find_edge (loop->latch, loop->header) == NULL)
+           {
+             error ("loop %d%'s latch has no edge to the header", i);
+             err = 1;
+           }
+       }
+ 
        if (loop->header->loop_father != loop)
        {
          error ("loop %d%'s header does not belong directly to it", i);
Index: gcc/testsuite/gcc.dg/torture/pr53695.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr53695.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr53695.c      (working copy)
***************
*** 0 ****
--- 1,14 ----
+ /* { dg-do compile } */
+ /* { dg-options "-ftracer" } */
+ 
+ void
+ foo (const void **p)
+ {
+   void *labs[] = { &&l1, &&l2, &&l3 };
+ l1:
+   goto *p++;
+ l2:
+   goto *p;
+ l3:
+   ;
+ }

Reply via email to