flow.c: Update comment.

* 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.

From-SVN: r23009
This commit is contained in:
John Wehle 1998-10-12 10:06:49 +00:00 committed by Jeff Law
parent 3babe36c37
commit fdb8a883a4
6 changed files with 81 additions and 13 deletions

View 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.

View 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)

View 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. */
#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));
/* 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)

View 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;

View 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;

View 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);
}