https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101260
--- Comment #10 from Stefan Schulze Frielinghaus <stefansf at linux dot ibm.com> --- In regcprop we call find_oldest_value_reg which itself calls maybe_mode_change (TImode, TImode, DImode, 10, 18) where we have regno += subreg_regno_offset (regno, orig_mode, offset, new_mode); The call is made where offset equals 8 which is wrong since we are interested in the high part which is contained in r10 and not r11. The following patch fixes this: diff --git a/gcc/regcprop.c b/gcc/regcprop.c index d2a01130fe1..0e1ac12458a 100644 --- a/gcc/regcprop.c +++ b/gcc/regcprop.c @@ -414,9 +414,14 @@ maybe_mode_change (machine_mode orig_mode, machine_mode copy_mode, copy_nregs, &bytes_per_reg)) return NULL_RTX; poly_uint64 copy_offset = bytes_per_reg * (copy_nregs - use_nregs); - poly_uint64 offset - = subreg_size_lowpart_offset (GET_MODE_SIZE (new_mode) + copy_offset, - GET_MODE_SIZE (orig_mode)); + poly_uint64 offset = +#if WORDS_BIG_ENDIAN + subreg_size_highpart_offset +#else + subreg_size_lowpart_offset +#endif + (GET_MODE_SIZE (new_mode) + copy_offset, + GET_MODE_SIZE (orig_mode)); regno += subreg_regno_offset (regno, orig_mode, offset, new_mode); if (targetm.hard_regno_mode_ok (regno, new_mode)) return gen_raw_REG (new_mode, regno); With the patch (insn 234 222 235 14 (set (reg:DI 10 %r10 [ a ]) (reg:DI 18 %f4)) 1376 {*movdi_64} (nil)) is first modified into a noop (insn 234 222 235 14 (set (reg:DI 10 %r10 [ a ]) (reg:DI 10 %r10 [18])) 1376 {*movdi_64} (nil)) and then deleted within regcprop.