Commit cc845923 by H.J. Lu Committed by H.J. Lu

Use word_mode to push/pop register for x86

2012-03-08  H.J. Lu  <hongjiu.lu@intel.com>

	* 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.
	(*push<mode>2_prologue): Replace :P with :W.
	(*pop<mode>1): Likewise.
	(*pop<mode>1_epilogue): Likewise.
	(push/pop peephole2): Use word_mode scratch registers.

From-SVN: r185123
parent 78d16236
2012-03-08 H.J. Lu <hongjiu.lu@intel.com>
* 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.
(*push<mode>2_prologue): Replace :P with :W.
(*pop<mode>1): Likewise.
(*pop<mode>1_epilogue): Likewise.
(push/pop peephole2): Use word_mode scratch registers.
2012-03-08 Uros Bizjak <ubizjak@gmail.com>
* config/i386/predicates.md (indirect_branch_operand): Simplify.
......
......@@ -7601,12 +7601,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)
......@@ -8661,8 +8662,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);
......@@ -8673,9 +8677,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)));
}
......@@ -9142,7 +9149,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;
}
}
......@@ -9222,7 +9229,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;
}
}
......@@ -10159,7 +10166,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;
......@@ -10356,14 +10363,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));
emit_move_insn (gen_rtx_REG (word_mode,
(eax_live ? AX_REG : R10_REG)),
gen_frame_mem (word_mode, t));
}
}
gcc_assert (m->fs.sp_offset == frame.stack_pointer_offset);
......@@ -10533,7 +10544,7 @@ ix86_emit_restore_regs_using_pop (void)
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (!SSE_REGNO_P (regno) && ix86_save_reg (regno, false))
ix86_emit_restore_reg_using_pop (gen_rtx_REG (Pmode, regno));
ix86_emit_restore_reg_using_pop (gen_rtx_REG (word_mode, regno));
}
/* Emit code and notes for the LEAVE instruction. */
......@@ -10576,11 +10587,11 @@ ix86_emit_restore_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, maybe_eh_return))
{
rtx reg = gen_rtx_REG (Pmode, regno);
rtx reg = gen_rtx_REG (word_mode, regno);
rtx insn, mem;
mem = choose_baseaddr (cfa_offset);
mem = gen_frame_mem (Pmode, mem);
mem = gen_frame_mem (word_mode, mem);
insn = emit_move_insn (reg, mem);
if (m->fs.cfa_reg == crtl->drap_reg && regno == REGNO (crtl->drap_reg))
......@@ -11185,8 +11196,8 @@ ix86_expand_split_stack_prologue (void)
{
rtx rax;
rax = gen_rtx_REG (Pmode, AX_REG);
emit_move_insn (rax, reg10);
rax = gen_rtx_REG (word_mode, AX_REG);
emit_move_insn (rax, gen_rtx_REG (word_mode, R10_REG));
use_reg (&call_fusage, rax);
}
......@@ -11265,8 +11276,8 @@ ix86_expand_split_stack_prologue (void)
/* If we are in 64-bit mode and this function uses a static chain,
we saved %r10 in %rax before calling _morestack. */
if (TARGET_64BIT && DECL_STATIC_CHAIN (cfun->decl))
emit_move_insn (gen_rtx_REG (Pmode, R10_REG),
gen_rtx_REG (Pmode, AX_REG));
emit_move_insn (gen_rtx_REG (word_mode, R10_REG),
gen_rtx_REG (word_mode, AX_REG));
/* If this function calls va_start, we need to store a pointer to
the arguments on the old stack, because they may not have been
......@@ -20275,7 +20286,7 @@ ix86_split_to_parts (rtx operand, rtx *parts, enum machine_mode mode)
gcc_assert (ok);
operand = copy_rtx (operand);
PUT_MODE (operand, Pmode);
PUT_MODE (operand, word_mode);
parts[0] = parts[1] = parts[2] = parts[3] = operand;
return size;
}
......@@ -20428,7 +20439,7 @@ ix86_split_long_move (rtx operands[])
if (push_operand (operands[0], VOIDmode))
{
operands[0] = copy_rtx (operands[0]);
PUT_MODE (operands[0], Pmode);
PUT_MODE (operands[0], word_mode);
}
else
operands[0] = gen_lowpart (DImode, operands[0]);
......@@ -894,6 +894,11 @@
;; pointer-sized quantities. Exactly one of the two alternatives will match.
(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
;; This mode iterator allows :W to be used for patterns that operate on
;; word_mode sized quantities.
(define_mode_iterator W
[(SI "word_mode == SImode") (DI "word_mode == DImode")])
;; This mode iterator allows :PTR to be used for patterns that operate on
;; ptr_mode sized quantities.
(define_mode_iterator PTR
......@@ -1702,8 +1707,8 @@
(set_attr "mode" "SI")])
(define_insn "*push<mode>2_prologue"
[(set (match_operand:P 0 "push_operand" "=<")
(match_operand:P 1 "general_no_elim_operand" "r<i>*m"))
[(set (match_operand:W 0 "push_operand" "=<")
(match_operand:W 1 "general_no_elim_operand" "r<i>*m"))
(clobber (mem:BLK (scratch)))]
""
"push{<imodesuffix>}\t%1"
......@@ -1711,16 +1716,16 @@
(set_attr "mode" "<MODE>")])
(define_insn "*pop<mode>1"
[(set (match_operand:P 0 "nonimmediate_operand" "=r*m")
(match_operand:P 1 "pop_operand" ">"))]
[(set (match_operand:W 0 "nonimmediate_operand" "=r*m")
(match_operand:W 1 "pop_operand" ">"))]
""
"pop{<imodesuffix>}\t%0"
[(set_attr "type" "pop")
(set_attr "mode" "<MODE>")])
(define_insn "*pop<mode>1_epilogue"
[(set (match_operand:P 0 "nonimmediate_operand" "=r*m")
(match_operand:P 1 "pop_operand" ">"))
[(set (match_operand:W 0 "nonimmediate_operand" "=r*m")
(match_operand:W 1 "pop_operand" ">"))
(clobber (mem:BLK (scratch)))]
""
"pop{<imodesuffix>}\t%0"
......@@ -17334,131 +17339,131 @@
;; alternative when no register is available later.
(define_peephole2
[(match_scratch:P 1 "r")
[(match_scratch:W 1 "r")
(parallel [(set (reg:P SP_REG)
(plus:P (reg:P SP_REG)
(match_operand:P 0 "const_int_operand" "")))
(clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"(TARGET_SINGLE_PUSH || optimize_insn_for_size_p ())
&& INTVAL (operands[0]) == -GET_MODE_SIZE (Pmode)"
&& INTVAL (operands[0]) == -GET_MODE_SIZE (word_mode)"
[(clobber (match_dup 1))
(parallel [(set (mem:P (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(parallel [(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(clobber (mem:BLK (scratch)))])])
(define_peephole2
[(match_scratch:P 1 "r")
[(match_scratch:W 1 "r")
(parallel [(set (reg:P SP_REG)
(plus:P (reg:P SP_REG)
(match_operand:P 0 "const_int_operand" "")))
(clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"(TARGET_DOUBLE_PUSH || optimize_insn_for_size_p ())
&& INTVAL (operands[0]) == -2*GET_MODE_SIZE (Pmode)"
&& INTVAL (operands[0]) == -2*GET_MODE_SIZE (word_mode)"
[(clobber (match_dup 1))
(set (mem:P (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(parallel [(set (mem:P (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(parallel [(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(clobber (mem:BLK (scratch)))])])
;; Convert esp subtractions to push.
(define_peephole2
[(match_scratch:P 1 "r")
[(match_scratch:W 1 "r")
(parallel [(set (reg:P SP_REG)
(plus:P (reg:P SP_REG)
(match_operand:P 0 "const_int_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"(TARGET_SINGLE_PUSH || optimize_insn_for_size_p ())
&& INTVAL (operands[0]) == -GET_MODE_SIZE (Pmode)"
&& INTVAL (operands[0]) == -GET_MODE_SIZE (word_mode)"
[(clobber (match_dup 1))
(set (mem:P (pre_dec:P (reg:P SP_REG))) (match_dup 1))])
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))])
(define_peephole2
[(match_scratch:P 1 "r")
[(match_scratch:W 1 "r")
(parallel [(set (reg:P SP_REG)
(plus:P (reg:P SP_REG)
(match_operand:P 0 "const_int_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"(TARGET_DOUBLE_PUSH || optimize_insn_for_size_p ())
&& INTVAL (operands[0]) == -2*GET_MODE_SIZE (Pmode)"
&& INTVAL (operands[0]) == -2*GET_MODE_SIZE (word_mode)"
[(clobber (match_dup 1))
(set (mem:P (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(set (mem:P (pre_dec:P (reg:P SP_REG))) (match_dup 1))])
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))])
;; Convert epilogue deallocator to pop.
(define_peephole2
[(match_scratch:P 1 "r")
[(match_scratch:W 1 "r")
(parallel [(set (reg:P SP_REG)
(plus:P (reg:P SP_REG)
(match_operand:P 0 "const_int_operand" "")))
(clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"(TARGET_SINGLE_POP || optimize_insn_for_size_p ())
&& INTVAL (operands[0]) == GET_MODE_SIZE (Pmode)"
[(parallel [(set (match_dup 1) (mem:P (post_inc:P (reg:P SP_REG))))
&& INTVAL (operands[0]) == GET_MODE_SIZE (word_mode)"
[(parallel [(set (match_dup 1) (mem:W (post_inc:P (reg:P SP_REG))))
(clobber (mem:BLK (scratch)))])])
;; Two pops case is tricky, since pop causes dependency
;; on destination register. We use two registers if available.
(define_peephole2
[(match_scratch:P 1 "r")
(match_scratch:P 2 "r")
[(match_scratch:W 1 "r")
(match_scratch:W 2 "r")
(parallel [(set (reg:P SP_REG)
(plus:P (reg:P SP_REG)
(match_operand:P 0 "const_int_operand" "")))
(clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"(TARGET_DOUBLE_POP || optimize_insn_for_size_p ())
&& INTVAL (operands[0]) == 2*GET_MODE_SIZE (Pmode)"
[(parallel [(set (match_dup 1) (mem:P (post_inc:P (reg:P SP_REG))))
&& INTVAL (operands[0]) == 2*GET_MODE_SIZE (word_mode)"
[(parallel [(set (match_dup 1) (mem:W (post_inc:P (reg:P SP_REG))))
(clobber (mem:BLK (scratch)))])
(set (match_dup 2) (mem:P (post_inc:P (reg:P SP_REG))))])
(set (match_dup 2) (mem:W (post_inc:P (reg:P SP_REG))))])
(define_peephole2
[(match_scratch:P 1 "r")
[(match_scratch:W 1 "r")
(parallel [(set (reg:P SP_REG)
(plus:P (reg:P SP_REG)
(match_operand:P 0 "const_int_operand" "")))
(clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"optimize_insn_for_size_p ()
&& INTVAL (operands[0]) == 2*GET_MODE_SIZE (Pmode)"
[(parallel [(set (match_dup 1) (mem:P (post_inc:P (reg:P SP_REG))))
&& INTVAL (operands[0]) == 2*GET_MODE_SIZE (word_mode)"
[(parallel [(set (match_dup 1) (mem:W (post_inc:P (reg:P SP_REG))))
(clobber (mem:BLK (scratch)))])
(set (match_dup 1) (mem:P (post_inc:P (reg:P SP_REG))))])
(set (match_dup 1) (mem:W (post_inc:P (reg:P SP_REG))))])
;; Convert esp additions to pop.
(define_peephole2
[(match_scratch:P 1 "r")
[(match_scratch:W 1 "r")
(parallel [(set (reg:P SP_REG)
(plus:P (reg:P SP_REG)
(match_operand:P 0 "const_int_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"INTVAL (operands[0]) == GET_MODE_SIZE (Pmode)"
[(set (match_dup 1) (mem:P (post_inc:P (reg:P SP_REG))))])
"INTVAL (operands[0]) == GET_MODE_SIZE (word_mode)"
[(set (match_dup 1) (mem:W (post_inc:P (reg:P SP_REG))))])
;; Two pops case is tricky, since pop causes dependency
;; on destination register. We use two registers if available.
(define_peephole2
[(match_scratch:P 1 "r")
(match_scratch:P 2 "r")
[(match_scratch:W 1 "r")
(match_scratch:W 2 "r")
(parallel [(set (reg:P SP_REG)
(plus:P (reg:P SP_REG)
(match_operand:P 0 "const_int_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"INTVAL (operands[0]) == 2*GET_MODE_SIZE (Pmode)"
[(set (match_dup 1) (mem:P (post_inc:P (reg:P SP_REG))))
(set (match_dup 2) (mem:P (post_inc:P (reg:P SP_REG))))])
"INTVAL (operands[0]) == 2*GET_MODE_SIZE (word_mode)"
[(set (match_dup 1) (mem:W (post_inc:P (reg:P SP_REG))))
(set (match_dup 2) (mem:W (post_inc:P (reg:P SP_REG))))])
(define_peephole2
[(match_scratch:P 1 "r")
[(match_scratch:W 1 "r")
(parallel [(set (reg:P SP_REG)
(plus:P (reg:P SP_REG)
(match_operand:P 0 "const_int_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"optimize_insn_for_size_p ()
&& INTVAL (operands[0]) == 2*GET_MODE_SIZE (Pmode)"
[(set (match_dup 1) (mem:P (post_inc:P (reg:P SP_REG))))
(set (match_dup 1) (mem:P (post_inc:P (reg:P SP_REG))))])
&& INTVAL (operands[0]) == 2*GET_MODE_SIZE (word_mode)"
[(set (match_dup 1) (mem:W (post_inc:P (reg:P SP_REG))))
(set (match_dup 1) (mem:W (post_inc:P (reg:P SP_REG))))])
;; Convert compares with 1 to shorter inc/dec operations when CF is not
;; required and register dies. Similarly for 128 to -128.
......@@ -17569,7 +17574,7 @@
;; leal (%edx,%eax,4), %eax
(define_peephole2
[(match_scratch:P 5 "r")
[(match_scratch:W 5 "r")
(parallel [(set (match_operand 0 "register_operand" "")
(ashift (match_operand 1 "register_operand" "")
(match_operand 2 "const_int_operand" "")))
......@@ -17595,16 +17600,16 @@
enum machine_mode op1mode = GET_MODE (operands[1]);
enum machine_mode mode = op1mode == DImode ? DImode : SImode;
int scale = 1 << INTVAL (operands[2]);
rtx index = gen_lowpart (Pmode, operands[1]);
rtx base = gen_lowpart (Pmode, operands[5]);
rtx index = gen_lowpart (word_mode, operands[1]);
rtx base = gen_lowpart (word_mode, operands[5]);
rtx dest = gen_lowpart (mode, operands[3]);
operands[1] = gen_rtx_PLUS (Pmode, base,
gen_rtx_MULT (Pmode, index, GEN_INT (scale)));
operands[1] = gen_rtx_PLUS (word_mode, base,
gen_rtx_MULT (word_mode, index, GEN_INT (scale)));
operands[5] = base;
if (mode != Pmode)
if (mode != word_mode)
operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
if (op1mode != Pmode)
if (op1mode != word_mode)
operands[5] = gen_rtx_SUBREG (op1mode, operands[5], 0);
operands[0] = dest;
})
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment