diff options
Diffstat (limited to 'gcc/ifcvt.c')
-rw-r--r-- | gcc/ifcvt.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 42c5fb50bdb..08612a968dc 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -645,8 +645,8 @@ noce_emit_store_flag (if_info, x, reversep, normalize) end_sequence (); } - /* Don't even try if the comparison operands are weird. */ - if (cond_complex) + /* Don't even try if the comparison operands or the mode of X are weird. */ + if (cond_complex || !SCALAR_INT_MODE_P (GET_MODE (x))) return NULL_RTX; return emit_store_flag (x, code, XEXP (cond, 0), @@ -1178,7 +1178,16 @@ noce_try_cmove_arith (if_info) tmp = gen_reg_rtx (GET_MODE (b)); tmp = emit_insn (gen_rtx_SET (VOIDmode, tmp, b)); } - else if (! insn_b) + else if (! insn_b +#if 0 + /* In the case we are going to duplicate insn originally + present in the front of comparsion, verify that the + comparsion didn't clobbered the operands. */ + || modified_between_p (SET_SRC (single_set (insn_b)), + if_info->cond_earliest, + NEXT_INSN (if_info->jump))) +#endif + ) goto end_seq_and_fail; else { @@ -1770,14 +1779,22 @@ noce_process_if_block (ce_info) else { insn_b = prev_nonnote_insn (if_info.cond_earliest); + /* We're going to be moving the evaluation of B down from above + COND_EARLIEST to JUMP. Make sure the relevant data is still + intact. */ if (! insn_b || GET_CODE (insn_b) != INSN || (set_b = single_set (insn_b)) == NULL_RTX || ! rtx_equal_p (x, SET_DEST (set_b)) + || reg_overlap_mentioned_p (x, SET_SRC (set_b)) + || modified_between_p (SET_SRC (set_b), + PREV_INSN (if_info.cond_earliest), jump) + /* Likewise with X. In particular this can happen when + noce_get_condition looks farther back in the instruction + stream than one might expect. */ || reg_overlap_mentioned_p (x, cond) || reg_overlap_mentioned_p (x, a) - || reg_overlap_mentioned_p (x, SET_SRC (set_b)) - || modified_between_p (x, if_info.cond_earliest, NEXT_INSN (jump))) + || modified_between_p (x, PREV_INSN (if_info.cond_earliest), jump)) insn_b = set_b = NULL_RTX; } b = (set_b ? SET_SRC (set_b) : x); |