+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
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
}
}
- /* 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 ();
| LOOPS_HAVE_PREHEADERS
| LOOPS_HAVE_SIMPLE_LATCHES
| LOOPS_HAVE_FALLTHRU_PREHEADERS);
+ loops_state_set (LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
goto loop_fini_done;
}
+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
--- /dev/null
+// { 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;
+ }
+}