From e7d70c6c3bccb2a1abed2683d436423cc5484704 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 2 May 2017 11:24:52 +0000 Subject: 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 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 --- gcc/tree-cfgcleanup.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'gcc/tree-cfgcleanup.c') diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c index 7eb7172..94a172f 100644 --- a/gcc/tree-cfgcleanup.c +++ b/gcc/tree-cfgcleanup.c @@ -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)); -- cgit v1.1