Hi! On the following testcase we have two endless loops before cddce2:
Sender_signal (int Connect) { int State; unsigned int occurrence; <bb 2>: if (Connect_6(D) != 0) goto <bb 8>; else goto <bb 7>; <bb 3>: # occurrence_8 = PHI <0(7), occurrence_12(4)> occurrence_12 = occurrence_8 + 1; __builtin_printf ("Sender_Signal occurrence %u\n", occurrence_12); <bb 4>: goto <bb 3>; <bb 5>: <bb 6>: goto <bb 5>; <bb 7>: goto <bb 3>; <bb 8>: goto <bb 5>; } The problem are the two empty bbs on the path from the conditional at the end of bb2 and the endless loops (i.e. bb7 and bb8). In presence of infinite loops dominance.c adds fake edges to exit pretty arbitrarily (it uses FOR_EACH_BB_REVERSE and for unconnected bbs computes post-dominance and adds fake edges to exit), so with the above testcases both bb7 and bb8 have exit block as immediate post-dominator, so find_control_dependence stops at those bb's when starting from the 2->7 resp. 2->8 edges. bb7/bb8 don't have a control stmt at the end, so mark_last_stmt_necessary doesn't mark any stmt as necessary in them and thus if (Connect_6(D) != 0) GIMPLE_COND is never marked as necessary and the whole endless loop with printfs in it is removed. The following patch fixes it by detecting such problematic blocks and recursing on them in mark_control_dependence_edges_necessary. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2012-10-22 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/55018 * tree-ssa-dce.c (mark_last_stmt_necessary): Return bool whether mark_stmt_necessary was called. (mark_control_dependence_edges_necessary): Recurse on cd_bb if mark_last_stmt_necessary hasn't marked a control stmt, cd_bb has exit block as immediate dominator and a single succ edge. * gcc.dg/torture/pr55018.c: New test. --- gcc/tree-ssa-dce.c.jj 2012-08-15 10:55:33.000000000 +0200 +++ gcc/tree-ssa-dce.c 2012-10-22 16:50:03.011497546 +0200 @@ -381,7 +381,7 @@ mark_stmt_if_obviously_necessary (gimple /* Mark the last statement of BB as necessary. */ -static void +static bool mark_last_stmt_necessary (basic_block bb) { gimple stmt = last_stmt (bb); @@ -391,7 +391,11 @@ mark_last_stmt_necessary (basic_block bb /* We actually mark the statement only if it is a control statement. */ if (stmt && is_ctrl_stmt (stmt)) - mark_stmt_necessary (stmt, true); + { + mark_stmt_necessary (stmt, true); + return true; + } + return false; } @@ -423,8 +427,18 @@ mark_control_dependent_edges_necessary ( continue; } - if (!TEST_BIT (last_stmt_necessary, cd_bb->index)) - mark_last_stmt_necessary (cd_bb); + if (!TEST_BIT (last_stmt_necessary, cd_bb->index) + && !mark_last_stmt_necessary (cd_bb)) + { + /* In presence of infinite loops, some bbs on a path + to an infinite loop might not end with a control stmt, + but due to a fake edge to exit stop find_control_dependence. + Recurse for those. */ + if (get_immediate_dominator (CDI_POST_DOMINATORS, cd_bb) + == EXIT_BLOCK_PTR + && single_succ_p (cd_bb)) + mark_control_dependent_edges_necessary (cd_bb, el, false); + } } if (!skipped) --- gcc/testsuite/gcc.dg/torture/pr55018.c.jj 2012-10-22 16:53:56.623083723 +0200 +++ gcc/testsuite/gcc.dg/torture/pr55018.c 2012-10-22 16:54:21.278934668 +0200 @@ -0,0 +1,22 @@ +/* PR tree-optimization/55018 */ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-optimized" } */ + +void +foo (int x) +{ + unsigned int a = 0; + int b = 3; + if (x) + b = 0; +lab: + if (x) + goto lab; + a++; + if (b != 2) + __builtin_printf ("%u", a); + goto lab; +} + +/* { dg-final { scan-tree-dump "printf" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ Jakub