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.

Reply via email to