]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR rtl-optimization/56181 (ICE in verify_loop_structure, at cfgloop.c:1581 with...
authorRichard Biener <rguenther@suse.de>
Fri, 8 Feb 2013 11:00:26 +0000 (11:00 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 8 Feb 2013 11:00:26 +0000 (11:00 +0000)
2013-02-08  Richard Biener  <rguenther@suse.de>

PR middle-end/56181
* cfgloop.h (flow_loops_find): Adjust.
(bb_loop_header_p): Declare.
* cfgloop.c (bb_loop_header_p): New function split out from ...
(flow_loops_find): ... here.  Adjust function signature,
support incremental loop structure update.
(verify_loop_structure): Cleanup.  Verify a loop is a loop.
* cfgloopmanip.c (fix_loop_structure): Move ...
* loop-init.c (fix_loop_structure): ... here.
(apply_loop_flags): Split out from ...
(loop_optimizer_init): ... here.
(fix_loop_structure): Use apply_loop_flags.  Use flow_loops_find
in incremental mode, only remove dead loops here.

* gcc.dg/torture/pr56181.c: New testcase.

From-SVN: r195879

gcc/ChangeLog
gcc/cfgloop.c
gcc/cfgloop.h
gcc/cfgloopmanip.c
gcc/loop-init.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr56181.c [new file with mode: 0644]

index 38173e97a1c0c7abe9c73a2ed5b6c3110f6b6152..5175c841a22e4b00e5fdb2350e407fd1f15e6a77 100644 (file)
@@ -1,3 +1,19 @@
+2013-02-08  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/56181
+       * cfgloop.h (flow_loops_find): Adjust.
+       (bb_loop_header_p): Declare.
+       * cfgloop.c (bb_loop_header_p): New function split out from ...
+       (flow_loops_find): ... here.  Adjust function signature,
+       support incremental loop structure update.
+       (verify_loop_structure): Cleanup.  Verify a loop is a loop.
+       * cfgloopmanip.c (fix_loop_structure): Move ...
+       * loop-init.c (fix_loop_structure): ... here.
+       (apply_loop_flags): Split out from ...
+       (loop_optimizer_init): ... here.
+       (fix_loop_structure): Use apply_loop_flags.  Use flow_loops_find
+       in incremental mode, only remove dead loops here.
+
 2013-02-08  Georg-Johann Lay  <avr@gjlay.de>
 
        PR target/54222
index 3c8df30cd7251e53ebe278a7ce75f1184eec0870..60fc6e8c31fd2c0c100a2567f5ea74f691f69177 100644 (file)
@@ -359,139 +359,156 @@ init_loops_structure (struct loops *loops, unsigned num_loops)
   loops->tree_root = root;
 }
 
+/* Returns whether HEADER is a loop header.  */
+
+bool
+bb_loop_header_p (basic_block header)
+{
+  edge_iterator ei;
+  edge e;
+
+  /* If we have an abnormal predecessor, do not consider the
+     loop (not worth the problems).  */
+  if (bb_has_abnormal_pred (header))
+    return false;
+
+  /* Look for back edges where a predecessor is dominated
+     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.  */
+  FOR_EACH_EDGE (e, ei, header->preds)
+    {
+      basic_block latch = e->src;
+      if (latch != ENTRY_BLOCK_PTR
+         && dominated_by_p (CDI_DOMINATORS, latch, header))
+       return true;
+    }
+
+  return false;
+}
+
 /* Find all the natural loops in the function and save in LOOPS structure and
    recalculate loop_father information in basic block structures.
-   Return the number of natural loops found.  */
+   If LOOPS is non-NULL then the loop structures for already recorded loops
+   will be re-used and their number will not change.  We assume that no
+   stale loops exist in LOOPS.
+   When LOOPS is NULL it is allocated and re-built from scratch.
+   Return the built LOOPS structure.  */
 
-int
+struct loops *
 flow_loops_find (struct loops *loops)
 {
-  int b;
-  int num_loops;
-  edge e;
-  sbitmap headers;
-  int *dfs_order;
+  bool from_scratch = (loops == NULL);
   int *rc_order;
-  basic_block header;
-  basic_block bb;
+  int b;
+  unsigned i;
+  vec<loop_p> larray;
 
   /* Ensure that the dominators are computed.  */
   calculate_dominance_info (CDI_DOMINATORS);
 
-  /* Taking care of this degenerate case makes the rest of
-     this code simpler.  */
-  if (n_basic_blocks == NUM_FIXED_BLOCKS)
+  if (!loops)
     {
+      loops = ggc_alloc_cleared_loops ();
       init_loops_structure (loops, 1);
-      return 1;
     }
 
-  dfs_order = NULL;
-  rc_order = NULL;
+  /* Ensure that loop exits were released.  */
+  gcc_assert (loops->exits == NULL);
 
-  /* Count the number of loop headers.  This should be the
-     same as the number of natural loops.  */
-  headers = sbitmap_alloc (last_basic_block);
-  bitmap_clear (headers);
+  /* Taking care of this degenerate case makes the rest of
+     this code simpler.  */
+  if (n_basic_blocks == NUM_FIXED_BLOCKS)
+    return loops;
 
-  num_loops = 0;
-  FOR_EACH_BB (header)
-    {
-      edge_iterator ei;
+  /* The root loop node contains all basic-blocks.  */
+  loops->tree_root->num_nodes = n_basic_blocks;
 
-      /* If we have an abnormal predecessor, do not consider the
-        loop (not worth the problems).  */
-      if (bb_has_abnormal_pred (header))
-       continue;
+  /* Compute depth first search order of the CFG so that outer
+     natural loops will be found before inner natural loops.  */
+  rc_order = XNEWVEC (int, n_basic_blocks);
+  pre_and_rev_post_order_compute (NULL, rc_order, false);
 
-      FOR_EACH_EDGE (e, ei, header->preds)
+  /* Gather all loop headers in reverse completion order and allocate
+     loop structures for loops that are not already present.  */
+  larray.create (loops->larray->length());
+  for (b = 0; b < n_basic_blocks - NUM_FIXED_BLOCKS; b++)
+    {
+      basic_block header = BASIC_BLOCK (rc_order[b]);
+      if (bb_loop_header_p (header))
        {
-         basic_block latch = e->src;
-
-         gcc_assert (!(e->flags & EDGE_ABNORMAL));
+         struct loop *loop;
 
-         /* Look for back edges where a predecessor is dominated
-            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))
+         /* The current active loop tree has valid loop-fathers for
+            header blocks.  */
+         if (!from_scratch
+             && header->loop_father->header == header)
            {
-             /* Shared headers should be eliminated by now.  */
-             bitmap_set_bit (headers, header->index);
-             num_loops++;
+             loop = header->loop_father;
+             /* If we found an existing loop remove it from the
+                loop tree.  It is going to be inserted again
+                below.  */
+             flow_loop_tree_node_remove (loop);
            }
+         else
+           {
+             /* Otherwise allocate a new loop structure for the loop.  */
+             loop = alloc_loop ();
+             /* ???  We could re-use unused loop slots here.  */
+             loop->num = loops->larray->length ();
+             vec_safe_push (loops->larray, loop);
+             loop->header = header;
+
+             if (!from_scratch
+                 && dump_file && (dump_flags & TDF_DETAILS))
+               fprintf (dump_file, "flow_loops_find: discovered new "
+                        "loop %d with header %d\n",
+                        loop->num, header->index);
+           }
+         larray.safe_push (loop);
        }
-    }
 
-  /* Allocate loop structures.  */
-  init_loops_structure (loops, num_loops + 1);
+      /* Make blocks part of the loop root node at start.  */
+      header->loop_father = loops->tree_root;
+    }
 
-  /* Find and record information about all the natural loops
-     in the CFG.  */
-  FOR_EACH_BB (bb)
-    bb->loop_father = loops->tree_root;
+  free (rc_order);
 
-  if (num_loops)
+  /* Now iterate over the loops found, insert them into the loop tree
+     and assign basic-block ownership.  */
+  for (i = 0; i < larray.length (); ++i)
     {
-      /* Compute depth first search order of the CFG so that outer
-        natural loops will be found before inner natural loops.  */
-      dfs_order = XNEWVEC (int, n_basic_blocks);
-      rc_order = XNEWVEC (int, n_basic_blocks);
-      pre_and_rev_post_order_compute (dfs_order, rc_order, false);
+      struct loop *loop = larray[i];
+      basic_block header = loop->header;
+      edge_iterator ei;
+      edge e;
 
-      num_loops = 1;
+      flow_loop_tree_node_add (header->loop_father, loop);
+      loop->num_nodes = flow_loop_nodes_find (loop->header, loop);
 
-      for (b = 0; b < n_basic_blocks - NUM_FIXED_BLOCKS; b++)
+      /* Look for the latch for this header block, if it has just a
+        single one.  */
+      FOR_EACH_EDGE (e, ei, header->preds)
        {
-         struct loop *loop;
-         edge_iterator ei;
-
-         /* Search the nodes of the CFG in reverse completion order
-            so that we can find outer loops first.  */
-         if (!bitmap_bit_p (headers, rc_order[b]))
-           continue;
-
-         header = BASIC_BLOCK (rc_order[b]);
-
-         loop = alloc_loop ();
-         loops->larray->quick_push (loop);
-
-         loop->header = header;
-         loop->num = num_loops;
-         num_loops++;
-
-         flow_loop_tree_node_add (header->loop_father, loop);
-         loop->num_nodes = flow_loop_nodes_find (loop->header, loop);
+         basic_block latch = e->src;
 
-         /* Look for the latch for this header block, if it has just a
-            single one.  */
-         FOR_EACH_EDGE (e, ei, header->preds)
+         if (flow_bb_inside_loop_p (loop, latch))
            {
-             basic_block latch = e->src;
-
-             if (flow_bb_inside_loop_p (loop, latch))
+             if (loop->latch != NULL)
                {
-                 if (loop->latch != NULL)
-                   {
-                     /* More than one latch edge.  */
-                     loop->latch = NULL;
-                     break;
-                   }
-                 loop->latch = latch;
+                 /* More than one latch edge.  */
+                 loop->latch = NULL;
+                 break;
                }
+             loop->latch = latch;
            }
        }
-
-      free (dfs_order);
-      free (rc_order);
     }
 
-  sbitmap_free (headers);
+  larray.release();
 
-  loops->exits = NULL;
-  return loops->larray->length ();
+  return loops;
 }
 
 /* Ratio of frequencies of edges so that one of more latch edges is
@@ -1300,7 +1317,7 @@ verify_loop_structure (void)
 {
   unsigned *sizes, i, j;
   sbitmap irreds;
-  basic_block *bbs, bb;
+  basic_block bb;
   struct loop *loop;
   int err = 0;
   edge e;
@@ -1308,7 +1325,7 @@ verify_loop_structure (void)
   loop_iterator li;
   struct loop_exit *exit, *mexit;
   bool dom_available = dom_info_available_p (CDI_DOMINATORS);
-  sbitmap visited = sbitmap_alloc (last_basic_block);
+  sbitmap visited;
 
   /* We need up-to-date dominators, compute or verify them.  */
   if (!dom_available)
@@ -1337,28 +1354,23 @@ verify_loop_structure (void)
     }
 
   /* Check get_loop_body.  */
-  FOR_EACH_LOOP (li, loop, 0)
-    {
-      bbs = get_loop_body (loop);
-
-      for (j = 0; j < loop->num_nodes; j++)
-       if (!flow_bb_inside_loop_p (loop, bbs[j]))
-         {
-           error ("bb %d does not belong to loop %d",
-                  bbs[j]->index, loop->num);
-           err = 1;
-         }
-      free (bbs);
-    }
+  visited = sbitmap_alloc (last_basic_block);
   bitmap_clear (visited);
   FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
     {
-      bbs = get_loop_body (loop);
+      basic_block *bbs = get_loop_body (loop);
 
       for (j = 0; j < loop->num_nodes; j++)
        {
          bb = bbs[j];
 
+         if (!flow_bb_inside_loop_p (loop, bb))
+           {
+             error ("bb %d does not belong to loop %d",
+                    bb->index, loop->num);
+             err = 1;
+           }
+
          /* Ignore this block if it is in an inner loop.  */
          if (bitmap_bit_p (visited, bb->index))
            continue;
@@ -1371,14 +1383,21 @@ verify_loop_structure (void)
              err = 1;
            }
        }
+
       free (bbs);
     }
+  sbitmap_free (visited);
 
   /* Check headers and latches.  */
   FOR_EACH_LOOP (li, loop, 0)
     {
       i = loop->num;
 
+      if (!bb_loop_header_p (loop->header))
+       {
+         error ("loop %d%'s header is not a loop header", i);
+         err = 1;
+       }
       if (loops_state_satisfies_p (LOOPS_HAVE_PREHEADERS)
          && EDGE_COUNT (loop->header->preds) != 2)
        {
@@ -1585,7 +1604,6 @@ verify_loop_structure (void)
 
   gcc_assert (!err);
 
-  sbitmap_free (visited);
   free (sizes);
   if (!dom_available)
     free_dominance_info (CDI_DOMINATORS);
index 071c8c1dd06983864ad5c769171e8bd4482e05ce..7506ac5758b4d1f9d71cafaf592d101f2517f148 100644 (file)
@@ -205,7 +205,8 @@ struct GTY (()) loops {
 };
 
 /* Loop recognition.  */
-extern int flow_loops_find (struct loops *);
+bool bb_loop_header_p (basic_block);
+extern struct loops *flow_loops_find (struct loops *);
 extern void disambiguate_loops_with_multiple_latches (void);
 extern void flow_loops_free (struct loops *);
 extern void flow_loops_dump (FILE *,
index c72cedaf74e5dbba438852516539bc7a0cf904b4..3e53aa0dddf8705f9545ca6553e1da6cfc96dbc8 100644 (file)
@@ -1760,159 +1760,3 @@ loop_version (struct loop *loop,
 
   return nloop;
 }
-
-/* The structure of loops might have changed.  Some loops might get removed
-   (and their headers and latches were set to NULL), loop exists might get
-   removed (thus the loop nesting may be wrong), and some blocks and edges
-   were changed (so the information about bb --> loop mapping does not have
-   to be correct).  But still for the remaining loops the header dominates
-   the latch, and loops did not get new subloops (new loops might possibly
-   get created, but we are not interested in them).  Fix up the mess.
-
-   If CHANGED_BBS is not NULL, basic blocks whose loop has changed are
-   marked in it.  */
-
-void
-fix_loop_structure (bitmap changed_bbs)
-{
-  basic_block bb;
-  struct loop *loop, *ploop;
-  loop_iterator li;
-  bool record_exits = false;
-  struct loop **superloop = XNEWVEC (struct loop *, number_of_loops ());
-
-  /* We need exact and fast dominance info to be available.  */
-  gcc_assert (dom_info_state (CDI_DOMINATORS) == DOM_OK);
-
-  /* Remove the old bb -> loop mapping.  Remember the depth of the blocks in
-     the loop hierarchy, so that we can recognize blocks whose loop nesting
-     relationship has changed.  */
-  FOR_EACH_BB (bb)
-    {
-      if (changed_bbs)
-       bb->aux = (void *) (size_t) loop_depth (bb->loop_father);
-      bb->loop_father = current_loops->tree_root;
-    }
-
-  if (loops_state_satisfies_p (LOOPS_HAVE_RECORDED_EXITS))
-    {
-      release_recorded_exits ();
-      record_exits = true;
-    }
-
-  /* First re-compute loop latches.  */
-  FOR_EACH_LOOP (li, loop, 0)
-    {
-      edge_iterator ei;
-      edge e, first_latch = NULL, latch = NULL;
-
-      if (!loop->header)
-       continue;
-
-      FOR_EACH_EDGE (e, ei, loop->header->preds)
-       if (dominated_by_p (CDI_DOMINATORS, e->src, loop->header))
-         {
-           if (!first_latch)
-             first_latch = latch = e;
-           else
-             {
-               latch = NULL;
-               break;
-             }
-         }
-      /* If there was no latch, schedule the loop for removal.  */
-      if (!first_latch)
-       loop->header = NULL;
-      /* If there was a single latch, record it.  */
-      else if (latch)
-       loop->latch = latch->src;
-      /* Otherwise there are multiple latches which are eventually
-         disambiguated below.  */
-      else
-       loop->latch = NULL;
-    }
-
-  /* Remove the dead loops from structures.  We start from the innermost
-     loops, so that when we remove the loops, we know that the loops inside
-     are preserved, and do not waste time relinking loops that will be
-     removed later.  */
-  FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
-    {
-      if (loop->header)
-       continue;
-
-      while (loop->inner)
-       {
-         ploop = loop->inner;
-         flow_loop_tree_node_remove (ploop);
-         flow_loop_tree_node_add (loop_outer (loop), ploop);
-       }
-
-      /* Remove the loop and free its data.  */
-      delete_loop (loop);
-    }
-
-  /* Rescan the bodies of loops, starting from the outermost ones.  We assume
-     that no optimization interchanges the order of the loops, i.e., it cannot
-     happen that L1 was superloop of L2 before and it is subloop of L2 now
-     (without explicitly updating loop information).  At the same time, we also
-     determine the new loop structure.  */
-  current_loops->tree_root->num_nodes = n_basic_blocks;
-  FOR_EACH_LOOP (li, loop, 0)
-    {
-      superloop[loop->num] = loop->header->loop_father;
-      loop->num_nodes = flow_loop_nodes_find (loop->header, loop);
-    }
-
-  /* Now fix the loop nesting.  */
-  FOR_EACH_LOOP (li, loop, 0)
-    {
-      ploop = superloop[loop->num];
-      if (ploop != loop_outer (loop))
-       {
-         flow_loop_tree_node_remove (loop);
-         flow_loop_tree_node_add (ploop, loop);
-       }
-    }
-  free (superloop);
-
-  /* Mark the blocks whose loop has changed.  */
-  if (changed_bbs)
-    {
-      FOR_EACH_BB (bb)
-       {
-         if ((void *) (size_t) loop_depth (bb->loop_father) != bb->aux)
-           bitmap_set_bit (changed_bbs, bb->index);
-
-         bb->aux = NULL;
-       }
-    }
-
-  if (!loops_state_satisfies_p (LOOPS_MAY_HAVE_MULTIPLE_LATCHES))
-    disambiguate_loops_with_multiple_latches ();
-
-  if (loops_state_satisfies_p (LOOPS_HAVE_PREHEADERS))
-    {
-      int cp_flags = CP_SIMPLE_PREHEADERS;
-
-      if (loops_state_satisfies_p (LOOPS_HAVE_FALLTHRU_PREHEADERS))
-       cp_flags |= CP_FALLTHRU_PREHEADERS;
-
-      create_preheaders (cp_flags);
-    }
-
-  if (loops_state_satisfies_p (LOOPS_HAVE_SIMPLE_LATCHES))
-    force_single_succ_latches ();
-
-  if (loops_state_satisfies_p (LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS))
-    mark_irreducible_loops ();
-
-  if (record_exits)
-    record_loop_exits ();
-
-  loops_state_clear (LOOPS_NEED_FIXUP);
-
-#ifdef ENABLE_CHECKING
-  verify_loop_structure ();
-#endif
-}
index 7e33de0f7e45df192c02f29da35589314e4da19f..d64c110c1b5dc1d6ae35b756df871cbbda58b668 100644 (file)
@@ -32,37 +32,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "ggc.h"
 
 \f
-/* Initialize loop structures.  This is used by the tree and RTL loop
-   optimizers.  FLAGS specify what properties to compute and/or ensure for
-   loops.  */
+/* Apply FLAGS to the loop state.  */
 
-void
-loop_optimizer_init (unsigned flags)
+static void
+apply_loop_flags (unsigned flags)
 {
-  timevar_push (TV_LOOP_INIT);
-  if (!current_loops)
-    {
-      struct loops *loops = ggc_alloc_cleared_loops ();
-
-      gcc_assert (!(cfun->curr_properties & PROP_loops));
-
-      /* Find the loops.  */
-
-      flow_loops_find (loops);
-      current_loops = loops;
-    }
-  else
-    {
-      gcc_assert (cfun->curr_properties & PROP_loops);
-
-      /* Ensure that the dominators are computed, like flow_loops_find does.  */
-      calculate_dominance_info (CDI_DOMINATORS);
-
-#ifdef ENABLE_CHECKING
-      verify_loop_structure ();
-#endif
-    }
-
   if (flags & LOOPS_MAY_HAVE_MULTIPLE_LATCHES)
     {
       /* If the loops may have multiple latches, we cannot canonicalize
@@ -97,6 +71,38 @@ loop_optimizer_init (unsigned flags)
 
   if (flags & LOOPS_HAVE_RECORDED_EXITS)
     record_loop_exits ();
+}
+
+/* Initialize loop structures.  This is used by the tree and RTL loop
+   optimizers.  FLAGS specify what properties to compute and/or ensure for
+   loops.  */
+
+void
+loop_optimizer_init (unsigned flags)
+{
+  timevar_push (TV_LOOP_INIT);
+
+  if (!current_loops)
+    {
+      gcc_assert (!(cfun->curr_properties & PROP_loops));
+
+      /* Find the loops.  */
+      current_loops = flow_loops_find (NULL);
+    }
+  else
+    {
+      gcc_assert (cfun->curr_properties & PROP_loops);
+
+      /* Ensure that the dominators are computed, like flow_loops_find does.  */
+      calculate_dominance_info (CDI_DOMINATORS);
+
+#ifdef ENABLE_CHECKING
+      verify_loop_structure ();
+#endif
+    }
+
+  /* Apply flags to loops.  */
+  apply_loop_flags (flags);
 
   /* Dump loops.  */
   flow_loops_dump (dump_file, NULL, 1);
@@ -157,6 +163,97 @@ loop_fini_done:
   timevar_pop (TV_LOOP_FINI);
 }
 
+/* The structure of loops might have changed.  Some loops might get removed
+   (and their headers and latches were set to NULL), loop exists might get
+   removed (thus the loop nesting may be wrong), and some blocks and edges
+   were changed (so the information about bb --> loop mapping does not have
+   to be correct).  But still for the remaining loops the header dominates
+   the latch, and loops did not get new subloops (new loops might possibly
+   get created, but we are not interested in them).  Fix up the mess.
+
+   If CHANGED_BBS is not NULL, basic blocks whose loop has changed are
+   marked in it.  */
+
+void
+fix_loop_structure (bitmap changed_bbs)
+{
+  basic_block bb;
+  int record_exits = 0;
+  loop_iterator li;
+  struct loop *loop;
+
+  timevar_push (TV_LOOP_INIT);
+
+  /* We need exact and fast dominance info to be available.  */
+  gcc_assert (dom_info_state (CDI_DOMINATORS) == DOM_OK);
+
+  if (loops_state_satisfies_p (LOOPS_HAVE_RECORDED_EXITS))
+    {
+      release_recorded_exits ();
+      record_exits = LOOPS_HAVE_RECORDED_EXITS;
+    }
+
+  /* Remember the depth of the blocks in the loop hierarchy, so that we can
+     recognize blocks whose loop nesting relationship has changed.  */
+  if (changed_bbs)
+    FOR_EACH_BB (bb)
+      bb->aux = (void *) (size_t) loop_depth (bb->loop_father);
+
+  /* Remove the dead loops from structures.  We start from the innermost
+     loops, so that when we remove the loops, we know that the loops inside
+     are preserved, and do not waste time relinking loops that will be
+     removed later.  */
+  FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
+    {
+      /* Detect the case that the loop is no longer present even though
+         it wasn't marked for removal.
+        ???  If we do that we can get away with not marking loops for
+        removal at all.  And possibly avoid some spurious removals.  */
+      if (loop->header
+         && bb_loop_header_p (loop->header))
+       continue;
+
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "fix_loop_structure: removing loop %d\n",
+                loop->num);
+
+      while (loop->inner)
+       {
+         struct loop *ploop = loop->inner;
+         flow_loop_tree_node_remove (ploop);
+         flow_loop_tree_node_add (loop_outer (loop), ploop);
+       }
+
+      /* Remove the loop and free its data.  */
+      delete_loop (loop);
+    }
+
+  /* Re-compute loop structure in-place.  */
+  flow_loops_find (current_loops);
+
+  /* Mark the blocks whose loop has changed.  */
+  if (changed_bbs)
+    {
+      FOR_EACH_BB (bb)
+       {
+         if ((void *) (size_t) loop_depth (bb->loop_father) != bb->aux)
+           bitmap_set_bit (changed_bbs, bb->index);
+
+         bb->aux = NULL;
+       }
+    }
+
+  loops_state_clear (LOOPS_NEED_FIXUP);
+
+  /* Apply flags to loops.  */
+  apply_loop_flags (current_loops->state | record_exits);
+
+#ifdef ENABLE_CHECKING
+  verify_loop_structure ();
+#endif
+
+  timevar_pop (TV_LOOP_INIT);
+}
 \f
 /* Gate for the RTL loop superpass.  The actual passes are subpasses.
    See passes.c for more on that.  */
index c12303dab8c98762fd1e49a3b485571345bc069e..2dcd876f9367c02440e3de8d7edb8bb2cae76765 100644 (file)
@@ -1,3 +1,8 @@
+2013-02-08  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/56181
+       * gcc.dg/torture/pr56181.c: New testcase.
+
 2013-02-08  Georg-Johann Lay  <avr@gjlay.de>
 
        PR target/54222
diff --git a/gcc/testsuite/gcc.dg/torture/pr56181.c b/gcc/testsuite/gcc.dg/torture/pr56181.c
new file mode 100644 (file)
index 0000000..c382b29
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */\r
+/* { dg-options "-ftracer" } */\r
+\r
+int a, b;\r
+\r
+void f(void)\r
+{\r
+  if(a++)\r
+    {\r
+      for(a = 0; a < 1;)\r
+       {\r
+         for(b = 0; b < 1; b++)\r
+           {\r
+             while(a++ < 0);\r
+lbl:\r
+             ;\r
+           }\r
+\r
+         if(a)\r
+           goto lbl;\r
+       }\r
+\r
+      goto lbl;\r
+    }\r
+}\r