machine_mode mode = GET_MODE (x);
auto old_num_changes = num_validated_changes ();
- if (from && GET_CODE (x) == GET_CODE (from) && rtx_equal_p (x, from))
+ if (from
+ && GET_CODE (x) == GET_CODE (from)
+ && (REG_P (x)
+ ? REGNO (x) == REGNO (from)
+ : rtx_equal_p (x, from)))
{
/* Don't replace register asms in asm statements; we mustn't
change the user's register allocation. */
&& asm_noperands (PATTERN (insn)) > 0)
return false;
+ rtx newval = to;
+ if (GET_MODE (x) != GET_MODE (from))
+ {
+ gcc_assert (REG_P (x) && HARD_REGISTER_P (x));
+ if (REG_NREGS (x) != REG_NREGS (from)
+ || !REG_CAN_CHANGE_MODE_P (REGNO (x), GET_MODE (from),
+ GET_MODE (x)))
+ return false;
+ newval = simplify_subreg (GET_MODE (x), to, GET_MODE (from),
+ subreg_lowpart_offset (GET_MODE (x),
+ GET_MODE (from)));
+ if (!newval)
+ return false;
+ }
+
if (should_unshare)
- validate_unshare_change (insn, loc, to, 1);
+ validate_unshare_change (insn, loc, newval, 1);
else
- validate_change (insn, loc, to, 1);
- if (mem_depth && !REG_P (to) && !CONSTANT_P (to))
+ validate_change (insn, loc, newval, 1);
+ if (mem_depth && !REG_P (newval) && !CONSTANT_P (newval))
{
/* We're substituting into an address, but TO will have the
form expected outside an address. Canonicalize it if
{
/* TO is owned by someone else, so create a copy and
return TO to its original form. */
- rtx to = copy_rtx (*loc);
+ newval = copy_rtx (*loc);
cancel_changes (old_num_changes);
- validate_change (insn, loc, to, 1);
+ validate_change (insn, loc, newval, 1);
}
}
num_replacements += 1;