Hi! The testcase below is miscompiled on x86_64-linux. The problem is that try_head_merge_bb uses df_get_bb_dirty to see if it can use df_get_live_out () info (through simulate_backwards_to_point) reliably, but as at -O1 the live problem isn't computed, only lr problem, df_get_live_out () returns the lr out bitmap, but df_get_bb_dirty which only looks at df_live problem always returns false. Thus, if the merge_bb's to compute live_union from for can_move_insns_across has dirty lr solution caused by earlier successful crossjumping in the same pass, we happily use its out of data lr bitmap.
Fixed by returning if the bb has dirty lr problem if live problem isn't computed. df_get_bb_dirty is only used here in crossjumping and in ifcvt, but in the latter we add the live problem at the start of ifcvt and remove it at the end of ifcvt for -O1. Bootstrapped/regtested on x86_64-linux, ok for trunk and 4.6.1? While it is a wrong-code bug, I doubt many people are using -O -fcrossjumping options together, and -fcrossjumping is only the default for -O2+, where live problem is added by default. 2011-03-18 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/48156 * df-core.c (df_get_bb_dirty): Use df_lr if df_live is NULL. * gcc.dg/pr48156.c: New test. --- 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; } --- gcc/testsuite/gcc.dg/pr48156.c.jj 2011-03-18 14:57:34.000000000 +0100 +++ gcc/testsuite/gcc.dg/pr48156.c 2011-03-18 14:57:14.000000000 +0100 @@ -0,0 +1,45 @@ +/* PR rtl-optimization/48156 */ +/* { dg-do run } */ +/* { dg-options "-O -fcrossjumping --param min-crossjump-insns=1" } */ + +extern void abort (void); + +static int __attribute__ ((noinline, noclone)) +equals (int s1, int s2) +{ + return s1 == s2; +} + +static int __attribute__ ((noinline, noclone)) +bar (void) +{ + return 1; +} + +static void __attribute__ ((noinline, noclone)) +baz (int f, int j) +{ + if (f != 4 || j != 2) + abort (); +} + +void +foo (int x) +{ + int i = 0, j = bar (); + + if (x == 1) + i = 2; + + if (j && equals (i, j)) + baz (8, i); + else + baz (4, i); +} + +int +main () +{ + foo (1); + return 0; +} Jakub