Use word_mode to push/pop register for x86
authorH.J. Lu <hongjiu.lu@intel.com>
Fri, 9 Mar 2012 04:17:02 +0000 (04:17 +0000)
committerH.J. Lu <hjl@gcc.gnu.org>
Fri, 9 Mar 2012 04:17:02 +0000 (20:17 -0800)
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

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.md

index 5f7d9fbc53b7ddac1e64080387dfc88bfba70005..c36c61cb761f139f906cec22c4c653947af5309d 100644 (file)
@@ -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.
index 666cf15cdf3ff4be56ae60934606608d7723ca49..15465c2efadf8e1d17ebec73f63dff4566f35405 100644 (file)
@@ -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]);
index a67a5e715c157bc734a02ded9c46be8a11bcafd2..188c9828038df50904c739bc854ba70f8f302fa6 100644 (file)
 ;; 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
    (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"
    (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"
 ;; 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))))])
 \f
 ;; Convert compares with 1 to shorter inc/dec operations when CF is not
 ;; required and register dies.  Similarly for 128 to -128.
 ;;  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" "")))
   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;
 })