In this case if-conversion sees if () (set (reg/v:SI 224 [ <retval> ]) (plus:SI (plus:SI (reg/v:SI 160 [ mod_tlen ]) (reg/v:SI 224 [ <retval> ])) (const_int 11 [0xb]) else (set (reg/v:SI 224 [ <retval> ]) (plus:SI (plus:SI (reg/v:SI 160 [ mod_tlen ]) (reg/v:SI 224 [ <retval> ])) (const_int 10 [0xa])))
where noce_try_store_flag_constants identifies (plus:SI (reg/v:SI 160 [ mod_tlen ]) (reg/v:SI 224 [ <retval> ])) as "common" and then tries to detect the case where setting the result would clobber that value. It doesn't seem to expect anything else than regs that can be equal to the destination though which is clearly an oversight. The following patch fixes this. Bootstrap and regtest running on x86_64-unknown-linux-gnu, I verified this fixes my observed ruby miscompile on i586-linux. Ok for trunk? Thanks, Richard. 2016-02-10 Richard Biener <rguent...@suse.de> PR rtl-optimization/69291 * ifcvt.c (noce_try_store_flag_constants): Properly handle common expressions. Index: gcc/ifcvt.c =================================================================== --- gcc/ifcvt.c (revision 233262) +++ gcc/ifcvt.c (working copy) @@ -1381,10 +1381,11 @@ noce_try_store_flag_constants (struct no /* If we have x := test ? x + 3 : x + 4 then move the original x out of the way while we store flags. */ - if (common && rtx_equal_p (common, if_info->x)) + if (common && reg_mentioned_p (if_info->x, common)) { - common = gen_reg_rtx (mode); - noce_emit_move_insn (common, if_info->x); + rtx tem = gen_reg_rtx (mode); + noce_emit_move_insn (tem, common); + common = tem; } target = noce_emit_store_flag (if_info, if_info->x, reversep, normalize);