From 867fdd05e4de59b21ea5fec6182127404cc94712 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 18 Dec 2012 14:39:49 +0000 Subject: re PR middle-end/54838 (ICE: in merge_latch_edges, at cfgloop.c:678 with -ftracer) 2012-12-18 Richard Biener 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/cfgloopmanip.c | 66 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 24 deletions(-) (limited to 'gcc/cfgloopmanip.c') 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 (); -- cgit v1.1