diff --git a/gcc/cprop.c b/gcc/cprop.c index c9fb2fc..42a2a72 100644 --- a/gcc/cprop.c +++ b/gcc/cprop.c @@ -758,12 +758,38 @@ try_replace_reg (rtx from, rtx to, rtx_insn *insn) int success = 0; rtx set = single_set (insn); + bool already_const_p = false; + bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)); + int old_cost = set ? set_rtx_cost (set, speed) : 0; + + if ((note != 0 + && REG_NOTE_KIND (note) == REG_EQUAL + && (GET_CODE (XEXP (note, 0)) == CONST + || CONSTANT_P (XEXP (note, 0)))) + || (set && CONSTANT_P (SET_SRC (set)))) + already_const_p = true; + /* Usually we substitute easy stuff, so we won't copy everything. We however need to take care to not duplicate non-trivial CONST expressions. */ to = copy_rtx (to); validate_replace_src_group (from, to, insn); + + + /* For CONSTANT_P (to), loop2_invariant pass might hoist it out the loop. + And it can be shared by different references. So skip propagation if + it makes INSN's rtx cost higher. */ + + if (!already_const_p + && CONSTANT_P (to) + && (set_rtx_cost (set, speed) > old_cost)) + { + cancel_changes (0); + return false; + } + + if (num_changes_pending () && apply_change_group ()) success = 1;