From: Richard Biener Date: Tue, 2 May 2017 11:24:52 +0000 (+0000) Subject: re PR tree-optimization/80549 (wrong code at -O2 and -O3 in both 32-bit and 64-bit... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e7d70c6c3bccb2a1abed2683d436423cc5484704;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4f7c9f7b1dd..5cbb7e77679 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +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. + 2017-05-02 Martin Liska PR other/80589 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3c526974534..5c4b7dfdeaf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-05-02 Richard Biener + + PR tree-optimization/80549 + * gcc.dg/torture/pr80549.c: New testcase. + 2017-05-02 Senthil Kumar Selvaraj * gcc.dg/pr78138.c: Use __SIZE_TYPE__ instead of diff --git a/gcc/testsuite/gcc.dg/torture/pr80549.c b/gcc/testsuite/gcc.dg/torture/pr80549.c new file mode 100644 index 00000000000..64ace5906ea --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr80549.c @@ -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; +} diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c index 7eb71724e92..94a172fa98e 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));