Re: PATCH: Use word_mode to push/pop register for x86

2012-03-08 Thread Uros Bizjak
On Tue, Mar 6, 2012 at 10:46 PM, H.J. Lu  wrote:

> push/pop in x86 only works on word_mode registers.  This patch properly
> handles push/pop on registers in x86.  Tested on Linux/x86-64.  OK for
> trunk?

> 2012-03-06  H.J. Lu  
>
>        * config/i386/i386.c (setup_incoming_varargs_64): Use word_mode
>        with integer parameters in registers.
>        (gen_push): Push register in word_mode instead of Pmode.
>        (ix86_emit_save_regs): Likewise.
>        (ix86_emit_save_regs_using_mov): Save integer registers in
>        word_mode.
>        (gen_pop): Pop register in word_mode instead of Pmode.
>        (ix86_emit_restore_regs_using_pop): Likewise.
>        (ix86_expand_prologue): Replace Pmode with word_mode for push
>        immediate.  Use ix86_gen_pro_epilogue_adjust_stack.  Save and
>        restore RAX and R10 in word_mode.
>        (ix86_emit_restore_regs_using_mov): Restore integer registers
>        in word_mode.
>        (ix86_expand_split_stack_prologue): Save R10_REG and restore in
>        word_mode.
>        (ix86_split_to_parts): Use word_mode with PUT_MODE for push.
>        (ix86_split_long_move): Likewise.
>
>        * config/i386/i386.md (W): New.
>        (*push2_prologue): Replace :P with :W.
>        (*pop1): Likewise.
>        (*pop1_epilogue): Likewise.
>        (push/pop peephole2): Use word_mode scratch registers.

The patch looks good to me. Based on the comment by Ian, I feel
confident that prologue/epilogue changes are OK, too. But I didn't
re-check all and every mode change here (since I can't test these
changes by myself), so please double check them. Admittely, the patch
doesn't break any x86 target.

So, OK for mainline.

Thanks,
Uros.


PATCH: Use word_mode to push/pop register for x86

2012-03-06 Thread H.J. Lu
Hi,

push/pop in x86 only works on word_mode registers.  This patch properly
handles push/pop on registers in x86.  Tested on Linux/x86-64.  OK for
trunk?

Thanks.


H.J.
---
2012-03-06  H.J. Lu  

* config/i386/i386.c (setup_incoming_varargs_64): Use word_mode
with integer parameters in registers.
(gen_push): Push register in word_mode instead of Pmode.
(ix86_emit_save_regs): Likewise.
(ix86_emit_save_regs_using_mov): Save integer registers in
word_mode.
(gen_pop): Pop register in word_mode instead of Pmode.
(ix86_emit_restore_regs_using_pop): Likewise.
(ix86_expand_prologue): Replace Pmode with word_mode for push
immediate.  Use ix86_gen_pro_epilogue_adjust_stack.  Save and
restore RAX and R10 in word_mode.
(ix86_emit_restore_regs_using_mov): Restore integer registers
in word_mode.
(ix86_expand_split_stack_prologue): Save R10_REG and restore in
word_mode.
(ix86_split_to_parts): Use word_mode with PUT_MODE for push.
(ix86_split_long_move): Likewise.

* config/i386/i386.md (W): New.
(*push2_prologue): Replace :P with :W.
(*pop1): Likewise.
(*pop1_epilogue): Likewise.
(push/pop peephole2): Use word_mode scratch registers.

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 973bbeb..eb4aaa8 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -7600,12 +7600,13 @@ setup_incoming_varargs_64 (CUMULATIVE_ARGS *cum)
 
   for (i = cum->regno; i < max; i++)
 {
-  mem = gen_rtx_MEM (Pmode,
+  mem = gen_rtx_MEM (word_mode,
 plus_constant (save_area, i * UNITS_PER_WORD));
   MEM_NOTRAP_P (mem) = 1;
   set_mem_alias_set (mem, set);
-  emit_move_insn (mem, gen_rtx_REG (Pmode,
-   x86_64_int_parameter_registers[i]));
+  emit_move_insn (mem,
+ gen_rtx_REG (word_mode,
+  x86_64_int_parameter_registers[i]));
 }
 
   if (ix86_varargs_fpr_size)
@@ -8660,8 +8661,11 @@ gen_push (rtx arg)
 m->fs.cfa_offset += UNITS_PER_WORD;
   m->fs.sp_offset += UNITS_PER_WORD;
 
+  if (REG_P (arg) && GET_MODE (arg) != word_mode)
+arg = gen_rtx_REG (word_mode, REGNO (arg));
+
   return gen_rtx_SET (VOIDmode,
- gen_rtx_MEM (Pmode,
+ gen_rtx_MEM (word_mode,
   gen_rtx_PRE_DEC (Pmode,
stack_pointer_rtx)),
  arg);
@@ -8672,9 +8676,12 @@ gen_push (rtx arg)
 static rtx
 gen_pop (rtx arg)
 {
+  if (REG_P (arg) && GET_MODE (arg) != word_mode)
+arg = gen_rtx_REG (word_mode, REGNO (arg));
+
   return gen_rtx_SET (VOIDmode,
  arg,
- gen_rtx_MEM (Pmode,
+ gen_rtx_MEM (word_mode,
   gen_rtx_POST_INC (Pmode,
 stack_pointer_rtx)));
 }
@@ -9141,7 +9148,7 @@ ix86_emit_save_regs (void)
   for (regno = FIRST_PSEUDO_REGISTER - 1; regno-- > 0; )
 if (!SSE_REGNO_P (regno) && ix86_save_reg (regno, true))
   {
-   insn = emit_insn (gen_push (gen_rtx_REG (Pmode, regno)));
+   insn = emit_insn (gen_push (gen_rtx_REG (word_mode, regno)));
RTX_FRAME_RELATED_P (insn) = 1;
   }
 }
@@ -9221,7 +9228,7 @@ ix86_emit_save_regs_using_mov (HOST_WIDE_INT cfa_offset)
   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
 if (!SSE_REGNO_P (regno) && ix86_save_reg (regno, true))
   {
-ix86_emit_save_reg_using_mov (Pmode, regno, cfa_offset);
+ix86_emit_save_reg_using_mov (word_mode, regno, cfa_offset);
cfa_offset -= UNITS_PER_WORD;
   }
 }
@@ -10158,7 +10165,7 @@ ix86_expand_prologue (void)
 to implement macro RETURN_ADDR_RTX and intrinsic function
 expand_builtin_return_addr etc.  */
   t = plus_constant (crtl->drap_reg, -UNITS_PER_WORD);
-  t = gen_frame_mem (Pmode, t);
+  t = gen_frame_mem (word_mode, t);
   insn = emit_insn (gen_push (t));
   RTX_FRAME_RELATED_P (insn) = 1;
 
@@ -10355,14 +10362,18 @@ ix86_expand_prologue (void)
   if (r10_live && eax_live)
 {
  t = choose_baseaddr (m->fs.sp_offset - allocate);
- emit_move_insn (r10, gen_frame_mem (Pmode, t));
+ emit_move_insn (gen_rtx_REG (word_mode, R10_REG),
+ gen_frame_mem (word_mode, t));
  t = choose_baseaddr (m->fs.sp_offset - allocate - UNITS_PER_WORD);
- emit_move_insn (eax, gen_frame_mem (Pmode, t));
+ emit_move_insn (gen_rtx_REG (word_mode, AX_REG),
+ gen_frame_mem (word_mode, t));
}
   else if (eax_live || r10_live)
{
  t = choose_baseaddr (m->fs.sp_offset - allocate);
- emit_move_insn ((eax_live ? eax : r10), gen_frame_mem (Pmode, t));