[backport gcc-4.8/trunk r196478, ChangeLogs were committed as part of the unrelated r196479 ] Date: Tue, 5 Mar 2013 17:26:46 +0100 From: Jakub Jelinek Subject: [PATCH] Avoid extending lifetime of likely spilled hard regs in ifcvt before reload (PR rtl-optimization/56484) List-Archive: Hi! Without this patch, ifcvt extends lifetime of %eax hard register, which causes reload/LRA ICE later on. Combiner and other passes try hard not to do that, even ifcvt has code for it if x is a hard register a few lines below it, but in this case the hard register is SET_SRC (set_b). With this patch we just use the pseudo (x) which has been initialized from the hard register before the conditional. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? gcc/ 2013-03-05 Jakub Jelinek PR rtl-optimization/56484 * ifcvt.c (noce_process_if_block): If else_bb is NULL, avoid extending lifetimes of hard registers on small register class machines. gcc/testsuite/ 2013-03-05 Jakub Jelinek PR rtl-optimization/56484 * gcc.c-torture/compile/pr56484.c: New test. --- gcc-4.7.2/gcc/ifcvt.c.~1~ 2012-02-27 15:30:44.000000000 +0100 +++ gcc-4.7.2/gcc/ifcvt.c 2013-03-09 12:59:47.690492428 +0100 @@ -2495,6 +2495,12 @@ noce_process_if_block (struct noce_if_in || ! noce_operand_ok (SET_SRC (set_b)) || reg_overlap_mentioned_p (x, SET_SRC (set_b)) || modified_between_p (SET_SRC (set_b), insn_b, jump) + /* Avoid extending the lifetime of hard registers on small + register class machines. */ + || (REG_P (SET_SRC (set_b)) + && HARD_REGISTER_P (SET_SRC (set_b)) + && targetm.small_register_classes_for_mode_p + (GET_MODE (SET_SRC (set_b)))) /* Likewise with X. In particular this can happen when noce_get_condition looks farther back in the instruction stream than one might expect. */ --- gcc-4.7.2/gcc/testsuite/gcc.c-torture/compile/pr56484.c.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.7.2/gcc/testsuite/gcc.c-torture/compile/pr56484.c 2013-03-09 12:59:47.690492428 +0100 @@ -0,0 +1,17 @@ +/* PR rtl-optimization/56484 */ + +unsigned char b[4096]; +int bar (void); + +int +foo (void) +{ + int a = 0; + while (bar ()) + { + int c = bar (); + a = a < 0 ? a : c; + __builtin_memset (b, 0, sizeof b); + } + return a; +}