diff options
author | H.J. Lu <hongjiu.lu@intel.com> | 2012-03-09 04:17:02 +0000 |
---|---|---|
committer | H.J. Lu <hjl@gcc.gnu.org> | 2012-03-08 20:17:02 -0800 |
commit | cc8459239b4a2dbdaf042e6e108cccaa249e554c (patch) | |
tree | 072d25a57e83bf59543cb61401b4ddeba4649ff5 /gcc | |
parent | 78d162367846e7cf9f0588bfb3be960caf3ed614 (diff) | |
download | gcc-cc8459239b4a2dbdaf042e6e108cccaa249e554c.zip gcc-cc8459239b4a2dbdaf042e6e108cccaa249e554c.tar.gz gcc-cc8459239b4a2dbdaf042e6e108cccaa249e554c.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 26 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 51 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 107 |
3 files changed, 113 insertions, 71 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5f7d9fb..c36c61c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +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. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 666cf15..15465c2 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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]); diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index a67a5e7..188c982 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -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; }) |