https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101260
--- Comment #10 from Stefan Schulze Frielinghaus ---
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, _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.