Hi,

This patch fixes PR61446.  The problem appears when we insert value copies 
after transformations. We use the widest extension mode met in a chain, but it 
may be wider than original destination register size.  This patch checks it and 
use smaller mode if required.

Bootstrapped and tested on linux-x86_64.

Does it look OK?

Thanks,
Ilya
--
2014-06-09  Ilya Enkovich  <ilya.enkov...@intel.com>

        PR 61446
        * ree.c (find_and_remove_re): Narrow mode for register copy
        if required.

diff --git a/gcc/ChangeLog.pr61446 b/gcc/ChangeLog.pr61446
new file mode 100644
index 0000000..b9e2148
--- /dev/null
+++ b/gcc/ChangeLog.pr61446
@@ -0,0 +1,5 @@
+2014-06-09  Ilya Enkovich  <ilya.enkov...@intel.com>
+
+       PR 61446
+       * ree.c (find_and_remove_re): Narrow mode for register copy
+       if required.
diff --git a/gcc/ree.c b/gcc/ree.c
index ade413e..6d34764 100644
--- a/gcc/ree.c
+++ b/gcc/ree.c
@@ -1088,14 +1088,24 @@ find_and_remove_re (void)
       /* Use the mode of the destination of the defining insn
         for the mode of the copy.  This is necessary if the
         defining insn was used to eliminate a second extension
-        that was wider than the first.  */
+        that was wider than the first.  Truncate mode if it is
+        too wide for destination reg.  */
       rtx sub_rtx = *get_sub_rtx (def_insn);
       rtx pat = PATTERN (curr_insn);
-      rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
-                                REGNO (XEXP (SET_SRC (pat), 0)));
-      rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
-                                REGNO (SET_DEST (pat)));
-      rtx set = gen_rtx_SET (VOIDmode, new_dst, new_src);
+      unsigned int regno = REGNO (XEXP (SET_SRC (pat), 0));
+      enum machine_mode mode = GET_MODE (SET_DEST (sub_rtx));
+      rtx new_dst, new_src, set;
+
+      if (HARD_REGNO_NREGS (regno, mode) != 1)
+       {
+         mode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (mode));
+         while (HARD_REGNO_NREGS (regno, GET_MODE_WIDER_MODE (mode)) == 1)
+           mode = GET_MODE_WIDER_MODE (mode);
+       }
+
+      new_dst = gen_rtx_REG (mode, REGNO (XEXP (SET_SRC (pat), 0)));
+      new_src = gen_rtx_REG (mode, REGNO (SET_DEST (pat)));
+      set = gen_rtx_SET (VOIDmode, new_dst, new_src);
       emit_insn_after (set, def_insn);
     }
 

Reply via email to