http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48156
--- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> 2011-03-18 13:32:13 UTC --- Actually, I think the bug is in df_get_bb_dirty: --- gcc/df-core.c.jj 2010-12-14 08:11:39.000000000 +0100 +++ gcc/df-core.c 2011-03-18 14:22:43.000000000 +0100 @@ -1400,10 +1400,16 @@ df_mark_solutions_dirty (void) bool df_get_bb_dirty (basic_block bb) { - if (df && df_live) - return bitmap_bit_p (df_live->out_of_date_transfer_functions, bb->index); - else - return false; + if (df) + { + if (df_live) + return bitmap_bit_p (df_live->out_of_date_transfer_functions, + bb->index); + else if (df_lr) + return bitmap_bit_p (df_lr->out_of_date_transfer_functions, + bb->index); + } + return false; } Both ifcvt.c and cfgcleanup.c via simulate_backwards_to_point call and use df_get_live_{in,out} (), which is: if (df_live) return DF_LIVE_OUT (bb); else return DF_LR_OUT (bb); On this testcase, df_live is NULL during crossjumping, so df_get_bb_dirty always returns false, even when the solution it is using is dirty. With the patch above cfgcleanup.c does the right thing, bails out from the merging when it is dirty and will df_analyze () afterwards and loop (as the dirtyness was caused by changes).