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
This commit is contained in:
Richard Biener 2012-12-18 14:39:49 +00:00 committed by Richard Biener
parent 0b8ca8fefe
commit 867fdd05e4
5 changed files with 159 additions and 24 deletions

View 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

View 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 ();

View 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;
}

View 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

View file

@ -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;
}
}