OSDN Git Service

* flow.c: Update comment.
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Oct 1998 10:06:49 +0000 (10:06 +0000)
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Oct 1998 10:06:49 +0000 (10:06 +0000)
        (notice_stack_pointer_modification): New static function.
        (record_volatile_insns): Use it.
        (mark_regs_live_at_end): Mark the stack pointer as alive
        at the end of the function if current_function_sp_is_unchanging
        is set.
        (life_analysis_1): Set current_function_sp_is_unchanging.
        * function.c: Define it.
        (init_function_start): Initialize it.
        * output.h: Declare it.
        * reorg.c (fill_simple_delay_slots, dbr_schedule): Mark
        the stack pointer as alive at the end of the function if
        current_function_sp_is_unchanging is set.
        * i386.c (ix86_epilogue): Optimize the restoring
        of the stack pointer.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@23009 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/flow.c
gcc/function.c
gcc/output.h
gcc/reorg.c

index ef57f79..2cb1e09 100644 (file)
@@ -1,3 +1,21 @@
+Sun Oct 11 16:49:15 EDT 1998  John Wehle  (john@feith.com)
+
+       * flow.c: Update comment.
+       (notice_stack_pointer_modification): New static function.
+       (record_volatile_insns): Use it.
+       (mark_regs_live_at_end): Mark the stack pointer as alive
+       at the end of the function if current_function_sp_is_unchanging
+       is set.
+       (life_analysis_1): Set current_function_sp_is_unchanging.
+       * function.c: Define it.
+       (init_function_start): Initialize it.
+       * output.h: Declare it.
+       * reorg.c (fill_simple_delay_slots, dbr_schedule): Mark
+       the stack pointer as alive at the end of the function if
+       current_function_sp_is_unchanging is set.
+       * i386.c (ix86_epilogue): Optimize the restoring
+       of the stack pointer.
+
 Mon Oct 12 02:03:25 1998  Jason Merrill  <jason@yorick.cygnus.com>
 
        * i386/t-cygwin32 (TARGET_LIBGCC2_CFLAGS): Define.
index fc8edbd..70cfcdc 100644 (file)
@@ -2294,6 +2294,7 @@ ix86_epilogue (do_rtl)
   rtx xops[3];
   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
                                  || current_function_uses_const_pool);
+  int sp_valid = !frame_pointer_needed || current_function_sp_is_unchanging;
   long tsize = get_frame_size ();
 
   /* Compute the number of registers to pop */
@@ -2307,12 +2308,7 @@ ix86_epilogue (do_rtl)
        || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
       nregs++;
 
-  /* sp is often  unreliable so we must go off the frame pointer.
-
-     In reality, we may not care if sp is unreliable, because we can restore
-     the register relative to the frame pointer.  In theory, since each move
-     is the same speed as a pop, and we don't need the leal, this is faster.
-     For now restore multiple registers the old way. */
+  /* sp is often unreliable so we may have to go off the frame pointer. */
 
   offset = - tsize - (nregs * UNITS_PER_WORD);
 
@@ -2329,9 +2325,14 @@ ix86_epilogue (do_rtl)
   if (flag_pic || profile_flag || profile_block_flag)
     emit_insn (gen_blockage ());
 
-  if (nregs > 1 || ! frame_pointer_needed)
+  /* If we're only restoring one register and sp is not valid then
+     using a move instruction to restore the register since it's
+     less work than reloading sp and popping the register.  Otherwise,
+     restore sp (if necessary) and pop the registers. */
+
+  if (nregs > 1 || sp_valid)
     {
-      if (frame_pointer_needed)
+      if ( !sp_valid )
        {
          xops[0] = adj_offsettable_operand (AT_BP (QImode), offset);
          if (do_rtl)
index 30618a4..0161d94 100644 (file)
@@ -106,7 +106,10 @@ Boston, MA 02111-1307, USA.  */
 
    life_analysis fills in certain vectors containing information about
    register usage: reg_n_refs, reg_n_deaths, reg_n_sets, reg_live_length,
-   reg_n_calls_crosses and reg_basic_block.  */
+   reg_n_calls_crosses and reg_basic_block.
+
+   life_analysis sets current_function_sp_is_unchanging if the function
+   doesn't modify the stack pointer.  */
 \f
 #include "config.h"
 #include "system.h"
@@ -289,6 +292,7 @@ static void init_regset_vector              PROTO ((regset *, int,
 static void count_reg_sets_1           PROTO ((rtx));
 static void count_reg_sets             PROTO ((rtx));
 static void count_reg_references       PROTO ((rtx));
+static void notice_stack_pointer_modification PROTO ((rtx, rtx));
 \f
 /* Find basic blocks of the current function.
    F is the first insn of the function and NREGS the number of register numbers
@@ -1221,9 +1225,28 @@ noop_move_p (insn)
   return 0;
 }
 
+static void
+notice_stack_pointer_modification (x, pat)
+     rtx x;
+     rtx pat ATTRIBUTE_UNUSED;
+{
+  if (x == stack_pointer_rtx
+      /* The stack pointer is only modified indirectly as the result
+        of a push until later in flow.  See the comments in rtl.texi
+        regarding Embedded Side-Effects on Addresses.  */
+      || (GET_CODE (x) == MEM
+         && (GET_CODE (XEXP (x, 0)) == PRE_DEC
+             || GET_CODE (XEXP (x, 0)) == PRE_INC
+             || GET_CODE (XEXP (x, 0)) == POST_DEC
+             || GET_CODE (XEXP (x, 0)) == POST_INC)
+         && XEXP (XEXP (x, 0), 0) == stack_pointer_rtx))
+    current_function_sp_is_unchanging = 0;
+}
+
 /* Record which insns refer to any volatile memory
    or for any reason can't be deleted just because they are dead stores.
-   Also, delete any insns that copy a register to itself.  */
+   Also, delete any insns that copy a register to itself.
+   And see if the stack pointer is modified.  */
 static void
 record_volatile_insns (f)
      rtx f;
@@ -1264,6 +1287,11 @@ record_volatile_insns (f)
              NOTE_SOURCE_FILE (insn) = 0;
            }
        }
+
+      /* Check if insn modifies the stack pointer.  */
+      if ( current_function_sp_is_unchanging
+          && GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+       note_stores (PATTERN (insn), notice_stack_pointer_modification);
     }
 }
 
@@ -1279,7 +1307,8 @@ mark_regs_live_at_end (set)
   if (! EXIT_IGNORE_STACK
       || (! FRAME_POINTER_REQUIRED
          && ! current_function_calls_alloca
-         && flag_omit_frame_pointer))
+         && flag_omit_frame_pointer)
+      || current_function_sp_is_unchanging)
 #endif
     /* If exiting needs the right stack value,
        consider the stack pointer live at the end of the function.  */
@@ -1376,6 +1405,11 @@ life_analysis_1 (f, nregs)
     = (regset *) alloca (n_basic_blocks * sizeof (regset));
   init_regset_vector (basic_block_significant, n_basic_blocks, &flow_obstack);
 
+  /* Assume that the stack pointer is unchanging if alloca hasn't been used.
+     This will be cleared by record_volatile_insns if it encounters an insn
+     which modifies the stack pointer.  */
+  current_function_sp_is_unchanging = !current_function_calls_alloca;
+
   record_volatile_insns (f);
 
   if (n_basic_blocks > 0)
index 4645f5a..48018cf 100644 (file)
@@ -138,6 +138,12 @@ int current_function_has_computed_jump;
 
 int current_function_contains_functions;
 
+/* Nonzero if function being compiled doesn't modify the stack pointer
+   (ignoring the prologue and epilogue).  This is only valid after
+   life_analysis has run. */
+
+int current_function_sp_is_unchanging;
+
 /* Nonzero if the current function is a thunk (a lightweight function that
    just adjusts one of its arguments and forwards to another function), so
    we should try to cut corners where we can.  */
@@ -5426,6 +5432,7 @@ init_function_start (subr, filename, line)
   current_function_has_nonlocal_label = 0;
   current_function_has_nonlocal_goto = 0;
   current_function_contains_functions = 0;
+  current_function_sp_is_unchanging = 0;
   current_function_is_thunk = 0;
 
   current_function_returns_pcc_struct = 0;
index 06d5204..83ec167 100644 (file)
@@ -380,6 +380,12 @@ extern int current_function_has_nonlocal_label;
 
 extern int current_function_contains_functions;
 
+/* Nonzero if function being compiled doesn't modify the stack pointer
+   (ignoring the prologue and epilogue).  This is only valid after
+   life_analysis has run. */
+
+extern int current_function_sp_is_unchanging;
+
 /* Nonzero if the current function returns a pointer type */
 
 extern int current_function_returns_pointer;
index 007d92e..d4c7778 100644 (file)
@@ -3452,7 +3452,8 @@ fill_simple_delay_slots (non_jumps_p)
       SET_HARD_REG_BIT (needed.regs, HARD_FRAME_POINTER_REGNUM);
 #endif
 #ifdef EXIT_IGNORE_STACK
-      if (! EXIT_IGNORE_STACK)
+      if (! EXIT_IGNORE_STACK
+         || current_function_sp_is_unchanging)
 #endif
        SET_HARD_REG_BIT (needed.regs, STACK_POINTER_REGNUM);
     }
@@ -4602,7 +4603,8 @@ dbr_schedule (first, file)
       SET_HARD_REG_BIT (end_of_function_needs.regs, HARD_FRAME_POINTER_REGNUM);
 #endif
 #ifdef EXIT_IGNORE_STACK
-      if (! EXIT_IGNORE_STACK)
+      if (! EXIT_IGNORE_STACK
+         || current_function_sp_is_unchanging)
 #endif
        SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM);
     }