On Fri, Nov 30, 2012 at 11:00:28PM +0100, Eric Botcazou wrote: > OK, let's tweak the patch as follows: > 1) when current_loops is not NULL, we compute may_be_loop_header and whether > the loop has more than 1 latch edge exactly, > 2) when current_loops is NULL, we use your above method to do the same, > 3) once this is done, we return from the function before entering the loop > if > this is a (potential) header with more than 1 (potential) latch edge. The > comment can say that threading through a loop header with more than 1 latch > edge is delicate and cite tree-threadupdate.c:thread_through_loop_header.
Like this? Regtested/bootstrapped on x86_64-linux, ok for trunk? 2012-12-01 Marek Polacek <pola...@redhat.com> PR middle-end/54838 * cprop.c (bypass_block): Determine number of latches. Return when there is more than one latch edge. * gcc.dg/pr54838.c: New test. --- gcc/cprop.c.mp 2012-11-29 15:49:53.120524295 +0100 +++ gcc/cprop.c 2012-12-01 16:14:59.387335461 +0100 @@ -1510,13 +1510,28 @@ bypass_block (basic_block bb, rtx setcc, if (note) find_used_regs (&XEXP (note, 0), NULL); - may_be_loop_header = false; - FOR_EACH_EDGE (e, ei, bb->preds) - if (e->flags & EDGE_DFS_BACK) - { - may_be_loop_header = true; - break; - } + /* Determine whether there are more latch edges. Threading through + a loop header with more than one latch is delicate, see e.g. + tree-ssa-threadupdate.c:thread_through_loop_header. */ + if (current_loops) + { + may_be_loop_header = bb == bb->loop_father->header; + if (may_be_loop_header + && bb->loop_father->latch == NULL) + return 0; + } + else + { + unsigned n_back_edges = 0; + FOR_EACH_EDGE (e, ei, bb->preds) + if (e->flags & EDGE_DFS_BACK) + n_back_edges++; + + may_be_loop_header = n_back_edges > 0; + + if (n_back_edges > 1) + return 0; + } change = 0; for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); ) --- gcc/testsuite/gcc.dg/pr54838.c.mp 2012-11-26 14:48:43.783980854 +0100 +++ gcc/testsuite/gcc.dg/pr54838.c 2012-11-26 14:49:51.051158719 +0100 @@ -0,0 +1,24 @@ +/* PR middle-end/54838 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-forward-propagate -ftracer" } */ + +void bar (void); + +void +foo (void *b, int *c) +{ +again: + switch (*c) + { + case 1: + if (!b) + { + bar (); + return; + } + goto again; + case 3: + if (!b) + goto again; + } +} Marek