So, here is the asked more complex variant regarding
displacement-value-range of amd64-instruction and taking care that we
use constant-offsets instead of register-based displacement addressing
if possible.

ChangeLog

2014-02-14  Kai Tietz  <kti...@redhat.com>

    PR target/60193
    * config/i386/i386.c (ix86_expand_prologue): Use
    rax register as displacement for restoring %r10, %eax.

Regression-tested for x86_64-unknown-linux-gnu, and
x86_64-w64-mingw32, and i686-w64-mingw32.  Ok for apply?

Regards,
Kai

Index: i386.c
===================================================================
--- i386.c    (Revision 207686)
+++ i386.c    (Arbeitskopie)
@@ -11084,17 +11084,34 @@ ix86_expand_prologue (void)
      works for realigned stack, too.  */
       if (r10_live && eax_live)
         {
-      t = plus_constant (Pmode, stack_pointer_rtx, allocate);
+      /* Don't exceed displacement-range for 64-bit.  */
+      if (!TARGET_64BIT || allocate <= (1 << 31))
+        t = plus_constant (Pmode, stack_pointer_rtx, allocate);
+      else
+        t = gen_rtx_PLUS (Pmode, stack_pointer_rtx, eax);
       emit_move_insn (gen_rtx_REG (word_mode, R10_REG),
               gen_frame_mem (word_mode, t));
-      t = plus_constant (Pmode, stack_pointer_rtx,
-                 allocate - UNITS_PER_WORD);
+
+      /* Don't exceed displacement-range for 64-bit.  */
+      if (!TARGET_64BIT || (allocate + UNITS_PER_WORD) <= (1 << 31))
+        t = plus_constant (Pmode, stack_pointer_rtx,
+                   allocate + UNITS_PER_WORD);
+      else
+        {
+          t = plus_constant (Pmode, eax, UNITS_PER_WORD);
+          emit_move_insn (eax, t);
+          t = gen_rtx_PLUS (Pmode, stack_pointer_rtx, eax);
+        }
       emit_move_insn (gen_rtx_REG (word_mode, AX_REG),
               gen_frame_mem (word_mode, t));
     }
       else if (eax_live || r10_live)
     {
-      t = plus_constant (Pmode, stack_pointer_rtx, allocate);
+      /* Don't exceed displacement-range for 64-bit.  */
+      if (!TARGET_64BIT || allocate <= (1 << 31))
+        t = plus_constant (Pmode, stack_pointer_rtx, allocate);
+      else
+        t = gen_rtx_PLUS (Pmode, stack_pointer_rtx, eax);
       emit_move_insn (gen_rtx_REG (word_mode,
                        (eax_live ? AX_REG : R10_REG)),
               gen_frame_mem (word_mode, t));

Reply via email to