i386.c (x86_accumulate_outgoing_args, [...]): New global variables.
authorJan Hubicka <jh@suse.cz>
Thu, 14 Jun 2001 10:45:38 +0000 (12:45 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Thu, 14 Jun 2001 10:45:38 +0000 (10:45 +0000)
* i386.c (x86_accumulate_outgoing_args, x86_prologue_using_move,
x86_epilogue_using_move): New global variables.
(override_options): Enable ACCUMULATE_OUTGOING_ARGS if preferred.
(ix86_emit_save_regs_using_mov): New static function.
(ix86_expand_prologue, ix86_expand_epilogue): Use moves if preferred.
* i386.h (MASK_MMX, MASK_SSE, MASK_SSE2, MASK_128BIT_LONG_DOUBLE,
MASK_MIX_SSE_I387): Renumber.
(MASK_NO_ACCUMULATE_OUTGOING_ARGS): New.
(x86_accumulate_outgoing_args, x86_prologue_using_move,
x86_epilogue_using_move): Declare.
(TARGET_PROLOGUE_USING_MOVE, TARGET_EPILOGUE_USING_MOVE): New.

From-SVN: r43366

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.h

index cdf54c68a755eb1716ba0db48cee00a7d4d095c7..37211422f58fe6a111c1376084979cf7df789831 100644 (file)
@@ -1,3 +1,17 @@
+Thu Jun 14 12:44:15 CEST 2001  Jan Hubicka  <jh@suse.cz>
+
+       * i386.c (x86_accumulate_outgoing_args, x86_prologue_using_move,
+       x86_epilogue_using_move): New global variables.
+       (override_options): Enable ACCUMULATE_OUTGOING_ARGS if preferred.
+       (ix86_emit_save_regs_using_mov): New static function.
+       (ix86_expand_prologue, ix86_expand_epilogue): Use moves if preferred.
+       * i386.h (MASK_MMX, MASK_SSE, MASK_SSE2, MASK_128BIT_LONG_DOUBLE,
+       MASK_MIX_SSE_I387): Renumber.
+       (MASK_NO_ACCUMULATE_OUTGOING_ARGS): New.
+       (x86_accumulate_outgoing_args, x86_prologue_using_move,
+       x86_epilogue_using_move): Declare.
+       (TARGET_PROLOGUE_USING_MOVE, TARGET_EPILOGUE_USING_MOVE): New.
+
 2001-06-13  John David Anglin  <dave@hiauly1.hia.nrc.ca>
 
        * inclhack.def (hpux10_cpp_pow_inline): New hack.
index cf60049447c23449baffe57ebd12fa0037f95190..af765db8c80540df7c77ac63e0b154486f8c6201 100644 (file)
@@ -313,6 +313,9 @@ const int x86_add_esp_8 = m_ATHLON | m_PPRO | m_K6 | m_386 | m_486 | m_PENT4;
 const int x86_integer_DFmode_moves = ~(m_ATHLON | m_PENT4);
 const int x86_partial_reg_dependency = m_ATHLON | m_PENT4;
 const int x86_memory_mismatch_stall = m_ATHLON | m_PENT4;
+const int x86_accumulate_outgoing_args = m_ATHLON | m_PENT4 | m_PPRO;
+const int x86_prologue_using_move = m_ATHLON | m_PENT4 | m_PPRO;
+const int x86_epilogue_using_move = m_ATHLON | m_PENT4 | m_PPRO;
 
 #define AT_BP(mode) (gen_rtx_MEM ((mode), hard_frame_pointer_rtx))
 
@@ -560,6 +563,7 @@ static int ix86_split_to_parts PARAMS ((rtx, rtx *, enum machine_mode));
 static int ix86_safe_length_prefix PARAMS ((rtx));
 static int ix86_nsaved_regs PARAMS((void));
 static void ix86_emit_save_regs PARAMS((void));
+static void ix86_emit_save_regs_using_mov PARAMS ((rtx, HOST_WIDE_INT));
 static void ix86_emit_restore_regs_using_mov PARAMS ((rtx, int, int));
 static void ix86_set_move_mem_attrs_1 PARAMS ((rtx, rtx, rtx, rtx, rtx));
 static void ix86_sched_reorder_pentium PARAMS((rtx *, rtx *));
@@ -835,6 +839,11 @@ override_options ()
      on by -msse.  */
   if (TARGET_SSE)
     target_flags |= MASK_MMX;
+
+  if ((x86_accumulate_outgoing_args & CPUMASK)
+      && !(target_flags & MASK_NO_ACCUMULATE_OUTGOING_ARGS)
+      && !optimize_size)
+    target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS;
 }
 \f
 void
@@ -2465,6 +2474,28 @@ ix86_emit_save_regs ()
       }
 }
 
+/* Emit code to save registers using MOV insns.  First register
+   is restored from POINTER + OFFSET.  */
+static void
+ix86_emit_save_regs_using_mov (pointer, offset)
+       rtx pointer;
+       HOST_WIDE_INT offset;
+{
+  int regno;
+  rtx insn;
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    if (ix86_save_reg (regno, true))
+      {
+       insn = emit_move_insn (adj_offsettable_operand (gen_rtx_MEM (Pmode,
+                                                                    pointer),
+                                                       offset),
+                              gen_rtx_REG (Pmode, regno));
+       RTX_FRAME_RELATED_P (insn) = 1;
+       offset += UNITS_PER_WORD;
+      }
+}
+
 /* Expand the prologue into a bunch of separate insns.  */
 
 void
@@ -2475,6 +2506,8 @@ ix86_expand_prologue ()
                                  || current_function_uses_const_pool)
                      && !TARGET_64BIT);
   struct ix86_frame frame;
+  int use_mov = (TARGET_PROLOGUE_USING_MOVE && !optimize_size);
+  HOST_WIDE_INT allocate;
 
   ix86_compute_frame_layout (&frame);
 
@@ -2490,9 +2523,18 @@ ix86_expand_prologue ()
       RTX_FRAME_RELATED_P (insn) = 1;
     }
 
-  ix86_emit_save_regs ();
+  allocate = frame.to_allocate;
+  /* In case we are dealing only with single register and empty frame,
+     push is equivalent of the mov+add sequence.  */
+  if (allocate == 0 && frame.nregs <= 1)
+    use_mov = 0;
 
-  if (frame.to_allocate == 0)
+  if (!use_mov)
+    ix86_emit_save_regs ();
+  else
+    allocate += frame.nregs * UNITS_PER_WORD;
+
+  if (allocate == 0)
     ;
   else if (! TARGET_STACK_PROBE || frame.to_allocate < CHECK_STACK_LIMIT)
     {
@@ -2511,7 +2553,7 @@ ix86_expand_prologue ()
        abort();
 
       arg0 = gen_rtx_REG (SImode, 0);
-      emit_move_insn (arg0, GEN_INT (frame.to_allocate));
+      emit_move_insn (arg0, GEN_INT (allocate));
 
       sym = gen_rtx_MEM (FUNCTION_MODE,
                         gen_rtx_SYMBOL_REF (Pmode, "_alloca"));
@@ -2521,6 +2563,14 @@ ix86_expand_prologue ()
        = gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_USE (VOIDmode, arg0),
                             CALL_INSN_FUNCTION_USAGE (insn));
     }
+  if (use_mov)
+    {
+      if (!frame_pointer_needed || !frame.to_allocate)
+        ix86_emit_save_regs_using_mov (stack_pointer_rtx, frame.to_allocate);
+      else
+        ix86_emit_save_regs_using_mov (hard_frame_pointer_rtx,
+                                      -frame.nregs * UNITS_PER_WORD);
+    }
 
 #ifdef SUBTARGET_PROLOGUE
   SUBTARGET_PROLOGUE;
@@ -2536,7 +2586,6 @@ ix86_expand_prologue ()
     emit_insn (gen_blockage ());
 }
 
-
 /* Emit code to restore saved registers using MOV insns.  First register
    is restored from POINTER + OFFSET.  */
 static void
@@ -2598,6 +2647,8 @@ ix86_expand_epilogue (style)
      and there is exactly one register to pop. This heruistic may need some
      tuning in future.  */
   if ((!sp_valid && frame.nregs <= 1)
+      || (TARGET_EPILOGUE_USING_MOVE && !optimize_size
+         && (frame.nregs > 1 || frame.to_allocate))
       || (frame_pointer_needed && !frame.nregs && frame.to_allocate)
       || (frame_pointer_needed && TARGET_USE_LEAVE && !optimize_size
          && frame.nregs == 1)
index 6803a0a57132d23257a4b1b8d228348da1bcd279..58d05cbf8a13b7b92f9c5fb6523d238b24198545 100644 (file)
@@ -114,13 +114,14 @@ extern int target_flags;
 #define MASK_INLINE_ALL_STROPS 0x00002000      /* Inline stringops in all cases */
 #define MASK_NO_PUSH_ARGS      0x00004000      /* Use push instructions */
 #define MASK_ACCUMULATE_OUTGOING_ARGS 0x00008000/* Accumulate outgoing args */
-#define MASK_MMX               0x00010000      /* Support MMX regs/builtins */
-#define MASK_SSE               0x00020000      /* Support SSE regs/builtins */
-#define MASK_SSE2              0x00040000      /* Support SSE2 regs/builtins */
-#define MASK_128BIT_LONG_DOUBLE 0x00080000     /* long double size is 128bit */
-#define MASK_MIX_SSE_I387      0x00100000      /* Mix SSE and i387 instructions */
-#define MASK_64BIT             0x00200000      /* Produce 64bit code */
-#define MASK_NO_RED_ZONE       0x00400000      /* Do not use red zone */
+#define MASK_NO_ACCUMULATE_OUTGOING_ARGS 0x00010000
+#define MASK_MMX               0x00020000      /* Support MMX regs/builtins */
+#define MASK_SSE               0x00040000      /* Support SSE regs/builtins */
+#define MASK_SSE2              0x00080000      /* Support SSE2 regs/builtins */
+#define MASK_128BIT_LONG_DOUBLE 0x00100000     /* long double size is 128bit */
+#define MASK_MIX_SSE_I387      0x00200000      /* Mix SSE and i387 instructions */
+#define MASK_64BIT             0x00400000      /* Produce 64bit code */
+#define MASK_NO_RED_ZONE       0x00800000      /* Do not use red zone */
 
 /* Temporary codegen switches */
 #define MASK_INTEL_SYNTAX      0x00000200
@@ -212,6 +213,8 @@ extern const int x86_himode_math, x86_qimode_math, x86_promote_qi_regs;
 extern const int x86_promote_hi_regs, x86_integer_DFmode_moves;
 extern const int x86_add_esp_4, x86_add_esp_8, x86_sub_esp_4, x86_sub_esp_8;
 extern const int x86_partial_reg_dependency, x86_memory_mismatch_stall;
+extern const int x86_accumulate_outgoing_args, x86_prologue_using_move;
+extern const int x86_epilogue_using_move;
 
 #define TARGET_USE_LEAVE (x86_use_leave & CPUMASK)
 #define TARGET_PUSH_MEMORY (x86_push_memory & CPUMASK)
@@ -247,6 +250,8 @@ extern const int x86_partial_reg_dependency, x86_memory_mismatch_stall;
 #define TARGET_INTEGER_DFMODE_MOVES (x86_integer_DFmode_moves & CPUMASK)
 #define TARGET_PARTIAL_REG_DEPENDENCY (x86_partial_reg_dependency & CPUMASK)
 #define TARGET_MEMORY_MISMATCH_STALL (x86_memory_mismatch_stall & CPUMASK)
+#define TARGET_PROLOGUE_USING_MOVE (x86_prologue_using_move & CPUMASK)
+#define TARGET_EPILOGUE_USING_MOVE (x86_epilogue_using_move & CPUMASK)
 
 #define TARGET_STACK_PROBE (target_flags & MASK_STACK_PROBE)