re PR tree-optimization/80549 (wrong code at -O2 and -O3 in both 32-bit and 64-bit modes on x86_64-linux-gnu (executable does not terminate))

2017-05-02  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/80549
	* tree-cfgcleanup.c (mfb_keep_latches): New helper.
	(cleanup_tree_cfg_noloop): Create forwarders to known loop
	headers if they do not have a preheader.

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

From-SVN: r247486
This commit is contained in:
Richard Biener 2017-05-02 11:24:52 +00:00 committed by Richard Biener
parent 51956afe27
commit e7d70c6c3b
4 changed files with 108 additions and 0 deletions

View file

@ -1,3 +1,10 @@
2017-05-02 Richard Biener <rguenther@suse.de>
PR tree-optimization/80549
* tree-cfgcleanup.c (mfb_keep_latches): New helper.
(cleanup_tree_cfg_noloop): Create forwarders to known loop
headers if they do not have a preheader.
2017-05-02 Martin Liska <mliska@suse.cz>
PR other/80589

View file

@ -1,3 +1,8 @@
2017-05-02 Richard Biener <rguenther@suse.de>
PR tree-optimization/80549
* gcc.dg/torture/pr80549.c: New testcase.
2017-05-02 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
* gcc.dg/pr78138.c: Use __SIZE_TYPE__ instead of

View file

@ -0,0 +1,33 @@
/* { dg-do run } */
signed char a, b;
int c;
short d;
void fn1(int p1)
{
short e = 4;
int f;
d = 0;
for (; d <= 0; d++)
e = 0;
if (e)
goto L1;
L2:
if (p1) {
a = 9;
for (; a; ++a) {
f = 5;
for (; f != 32; ++f)
c = 8;
L1:
if (b)
goto L2;
}
}
}
int main()
{
fn1(1);
return 0;
}

View file

@ -739,6 +739,11 @@ cleanup_tree_cfg_1 (void)
return retval;
}
static bool
mfb_keep_latches (edge e)
{
return ! dominated_by_p (CDI_DOMINATORS, e->src, e->dest);
}
/* Remove unreachable blocks and other miscellaneous clean up work.
Return true if the flowgraph was modified, false otherwise. */
@ -766,6 +771,64 @@ cleanup_tree_cfg_noloop (void)
changed = false;
}
/* Ensure that we have single entries into loop headers. Otherwise
if one of the entries is becoming a latch due to CFG cleanup
(from formerly being part of an irreducible region) then we mess
up loop fixup and associate the old loop with a different region
which makes niter upper bounds invalid. See for example PR80549.
This needs to be done before we remove trivially dead edges as
we need to capture the dominance state before the pending transform. */
if (current_loops)
{
loop_p loop;
unsigned i;
FOR_EACH_VEC_ELT (*get_loops (cfun), i, loop)
if (loop && loop->header)
{
basic_block bb = loop->header;
edge_iterator ei;
edge e;
bool found_latch = false;
bool any_abnormal = false;
unsigned n = 0;
/* We are only interested in preserving existing loops, but
we need to check whether they are still real and of course
if we need to add a preheader at all. */
FOR_EACH_EDGE (e, ei, bb->preds)
{
if (e->flags & EDGE_ABNORMAL)
{
any_abnormal = true;
break;
}
if (dominated_by_p (CDI_DOMINATORS, e->src, bb))
{
found_latch = true;
continue;
}
n++;
}
/* If we have more than one entry to the loop header
create a forwarder. */
if (found_latch && ! any_abnormal && n > 1)
{
edge fallthru = make_forwarder_block (bb, mfb_keep_latches,
NULL);
loop->header = fallthru->dest;
if (! loops_state_satisfies_p (LOOPS_NEED_FIXUP))
{
/* The loop updating from the CFG hook is incomplete
when we have multiple latches, fixup manually. */
remove_bb_from_loops (fallthru->src);
loop_p cloop = loop;
FOR_EACH_EDGE (e, ei, fallthru->src->preds)
cloop = find_common_loop (cloop, e->src->loop_father);
add_bb_to_loop (fallthru->src, cloop);
}
}
}
}
changed |= cleanup_tree_cfg_1 ();
gcc_assert (dom_info_available_p (CDI_DOMINATORS));