]> gcc.gnu.org Git - gcc.git/commitdiff
re PR middle-end/54838 (ICE: in merge_latch_edges, at cfgloop.c:678 with -ftracer)
authorRichard Biener <rguenther@suse.de>
Tue, 18 Dec 2012 14:39:49 +0000 (14:39 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 18 Dec 2012 14:39:49 +0000 (14:39 +0000)
2012-12-18  Richard Biener  <rguenther@suse.de>

PR middle-end/54838
* cfgloopmanip.c (fix_loop_structure): Re-discover latch
edges first and mark loops for removal if no latch edges remain.
Properly re-create LOOPS_HAVE_FALLTHRU_PREHEADERS.
* loop-init.c (loop_optimizer_finalize): Set
LOOPS_MAY_HAVE_MULTIPLE_LATCHES.

* g++.dg/torture/pr54838.C: New testcase.

From-SVN: r194582

gcc/ChangeLog
gcc/cfgloopmanip.c
gcc/loop-init.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr54838.C [new file with mode: 0644]

index b032c96abe9822968b8747a888abcfe1f6a049b3..16bc6664322efc6b4c633de03dc65dcb0b3e16d1 100644 (file)
@@ -1,3 +1,12 @@
+2012-12-18  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/54838
+       * cfgloopmanip.c (fix_loop_structure): Re-discover latch
+       edges first and mark loops for removal if no latch edges remain.
+       Properly re-create LOOPS_HAVE_FALLTHRU_PREHEADERS.
+       * loop-init.c (loop_optimizer_finalize): Set
+       LOOPS_MAY_HAVE_MULTIPLE_LATCHES.
+
 2012-12-18  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/55555
index 34f730166088992d297679e44d6ec071062da232..64f6f6437384c0245e65b65f8456dac162237524 100644 (file)
@@ -1793,6 +1793,40 @@ fix_loop_structure (bitmap changed_bbs)
       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 and it belongs to the loop of the
+        header, record it.  */
+      else if (latch
+              && latch->src->loop_father == loop)
+       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
@@ -1849,34 +1883,18 @@ fix_loop_structure (bitmap changed_bbs)
        }
     }
 
-  /* Then re-compute the single latch if there is one.  */
-  FOR_EACH_LOOP (li, loop, 0)
-    {
-      edge_iterator ei;
-      edge e, latch = NULL;
-      FOR_EACH_EDGE (e, ei, loop->header->preds)
-       if (dominated_by_p (CDI_DOMINATORS, e->src, loop->header))
-         {
-           if (!latch)
-             latch = e;
-           else
-             {
-               latch = NULL;
-               break;
-             }
-         }
-      if (latch
-         && latch->src->loop_father == loop)
-       loop->latch = latch->src;
-      else
-       loop->latch = NULL;
-    }
-
   if (!loops_state_satisfies_p (LOOPS_MAY_HAVE_MULTIPLE_LATCHES))
     disambiguate_loops_with_multiple_latches ();
 
   if (loops_state_satisfies_p (LOOPS_HAVE_PREHEADERS))
-    create_preheaders (CP_SIMPLE_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 ();
index f140686ba1168534b3ee8137a0cf3e2cdb4cb8e2..b981762a385ac7733910cd7150d0cff09a6cd75e 100644 (file)
@@ -133,6 +133,7 @@ loop_optimizer_finalize (void)
                         | LOOPS_HAVE_PREHEADERS
                         | LOOPS_HAVE_SIMPLE_LATCHES
                         | LOOPS_HAVE_FALLTHRU_PREHEADERS);
+      loops_state_set (LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
       goto loop_fini_done;
     }
 
index 7bc7788c115e0244901b6be955ac19e740a725c0..dcb4bd943924a71d33899548c4c994b4528fc431 100644 (file)
@@ -1,3 +1,8 @@
+2012-12-18  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/54838
+       * g++.dg/torture/pr54838.C: New testcase.
+
 2012-12-18  Andreas Schwab  <schwab@linux-m68k.org>
 
        * lib/go.exp (go_link_flags): Add libatomic location to flags and
diff --git a/gcc/testsuite/g++.dg/torture/pr54838.C b/gcc/testsuite/g++.dg/torture/pr54838.C
new file mode 100644 (file)
index 0000000..6d34d57
--- /dev/null
@@ -0,0 +1,102 @@
+// { dg-do compile }
+// { dg-options "-ftracer -fno-tree-dce -fno-tree-sra" }
+
+struct bidirectional_iterator_tag
+{};
+struct random_access_iterator_tag:bidirectional_iterator_tag
+{};
+template < typename _Category, typename, typename _Distance, typename > struct iterator
+{
+  typedef _Distance difference_type;
+};
+template < typename _Iterator > struct iterator_traits
+{
+  typedef typename _Iterator::difference_type difference_type;
+};
+template < typename _Tp > struct iterator_traits <_Tp * >
+{
+  typedef random_access_iterator_tag iterator_category;
+  typedef _Tp value_type;
+  typedef int difference_type;
+  typedef _Tp reference;
+};
+template < typename _Iterator > class reverse_iterator:
+    public
+    iterator < typename iterator_traits < _Iterator >::iterator_category,
+    typename iterator_traits < _Iterator >::value_type,
+    typename iterator_traits < _Iterator >::difference_type, typename iterator_traits < _Iterator >::reference >
+{
+  _Iterator current;
+public:
+  typedef _Iterator iterator_type;
+  reverse_iterator (const reverse_iterator & __x):current (__x.current)
+  {}
+  iterator_type base ()
+    {
+      return current;
+    }
+  reverse_iterator operator++ ()
+    {
+      --current;
+    }
+};
+template
+<
+typename
+_Iterator
+>
+bool
+operator
+==
+(reverse_iterator < _Iterator > __x, reverse_iterator < _Iterator > __y)
+{
+  return __x.base () == __y.base ();
+}
+
+template
+<
+typename
+_Iterator
+>
+typename
+reverse_iterator
+<
+_Iterator
+>::difference_type
+operator
+- (reverse_iterator < _Iterator >, reverse_iterator < _Iterator >)
+{}
+template
+<
+typename
+_RandomAccessIterator
+>
+_RandomAccessIterator
+__find
+(_RandomAccessIterator
+ __first, _RandomAccessIterator __last)
+{
+  typename
+      iterator_traits
+      <
+      _RandomAccessIterator
+      >::difference_type __trip_count (__last - __first);
+  for (; __trip_count; --__trip_count)
+    ++__first;
+  return __last;
+}
+typedef reverse_iterator < int* > _ForwardIterator1;
+_ForwardIterator1
+search
+(_ForwardIterator1
+ __first1,
+ _ForwardIterator1
+ __last1)
+{
+  for (;;)
+    {
+      __first1 = __find (__first1, __last1);
+      if (__first1 == __last1)
+       return __last1;
+    }
+}
This page took 0.103177 seconds and 5 git commands to generate.