aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2012-12-18 14:39:49 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2012-12-18 14:39:49 +0000
commit867fdd05e4de59b21ea5fec6182127404cc94712 (patch)
tree965e63d5d06c276a59bece27337abea448f54c59 /gcc
parent0b8ca8fefec7479e91654819be9b77362406b1b5 (diff)
downloadgcc-867fdd05e4de59b21ea5fec6182127404cc94712.zip
gcc-867fdd05e4de59b21ea5fec6182127404cc94712.tar.gz
gcc-867fdd05e4de59b21ea5fec6182127404cc94712.tar.bz2
re PR middle-end/54838 (ICE: in merge_latch_edges, at cfgloop.c:678 with -ftracer)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/cfgloopmanip.c66
-rw-r--r--gcc/loop-init.c1
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/torture/pr54838.C102
5 files changed, 159 insertions, 24 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b032c96..16bc666 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,14 @@
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
* tree-ssa-loop-niter.c (idx_infer_loop_bounds): Properly
analyze evolution of the index for the loop it is used in.
diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c
index 34f7301..64f6f64 100644
--- a/gcc/cfgloopmanip.c
+++ b/gcc/cfgloopmanip.c
@@ -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 ();
diff --git a/gcc/loop-init.c b/gcc/loop-init.c
index f140686..b981762 100644
--- a/gcc/loop-init.c
+++ b/gcc/loop-init.c
@@ -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;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7bc7788c..dcb4bd9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..6d34d57
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr54838.C
@@ -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;
+ }
+}