[backport gcc-4.7/trunk r182919 PR49710 fix which reportedly also fixes PR48813 ] gcc/ 2012-01-05 Jan Hubicka PR middle-end/49710 * cfgloopmanip.c (remove_path): Walk loop hiearchy upwards when unlooping loops. gcc/testsuite/ 2012-01-05 Jan Hubicka PR middle-end/49710 * gcc.c-torture/compile/pr49710.c: New file. --- gcc-4.6.2/gcc/cfgloopmanip.c.~1~ 2011-03-07 17:41:53.000000000 +0100 +++ gcc-4.6.2/gcc/cfgloopmanip.c 2012-02-18 20:39:09.000000000 +0100 @@ -290,6 +290,7 @@ remove_path (edge e) int i, nrem, n_bord_bbs; sbitmap seen; bool irred_invalidated = false; + struct loop *l, *f; if (!can_remove_branch_p (e)) return false; @@ -313,10 +314,12 @@ remove_path (edge e) we belong to. In this case first unloop the loops, then proceed normally. We may assume that e->dest is not a header of any loop, as it now has exactly one predecessor. */ - while (loop_outer (e->src->loop_father) - && dominated_by_p (CDI_DOMINATORS, - e->src->loop_father->latch, e->dest)) - unloop (e->src->loop_father, &irred_invalidated); + for (l = e->src->loop_father; loop_outer (l); l = f) + { + f = loop_outer (l); + if (dominated_by_p (CDI_DOMINATORS, l->latch, e->dest)) + unloop (l, &irred_invalidated); + } /* Identify the path. */ nrem = find_path (e, &rem_bbs); --- gcc-4.6.2/gcc/testsuite/gcc.c-torture/compile/pr49710.c.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.6.2/gcc/testsuite/gcc.c-torture/compile/pr49710.c 2012-02-18 20:39:09.000000000 +0100 @@ -0,0 +1,35 @@ +int a, b, c, d; + +static void +foo (int *x) +{ + c = 0; + while (1) + { + if (*x) +break; + while (b) +for (; c; c = 0); + for (d = 18; d != 18; d++) +if (c) + { + foo (x); + return; + } + } +} + +static void +bar () +{ + foo (0); + foo (0); + for (;;) + ; +} + +baz () +{ + for (; a;) + bar (); +}