From fdb8a883a4f3415aec0434737c9446f80d0133f0 Mon Sep 17 00:00:00 2001 From: John Wehle Date: Mon, 12 Oct 1998 10:06:49 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 18 ++++++++++++++++++ gcc/config/i386/i386.c | 17 +++++++++-------- gcc/flow.c | 40 +++++++++++++++++++++++++++++++++++++--- gcc/function.c | 7 +++++++ gcc/output.h | 6 ++++++ gcc/reorg.c | 6 ++++-- 6 files changed, 81 insertions(+), 13 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ef57f796b63..2cb1e09631d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 * i386/t-cygwin32 (TARGET_LIBGCC2_CFLAGS): Define. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index fc8edbd64d1..70cfcdc500b 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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) diff --git a/gcc/flow.c b/gcc/flow.c index 30618a47a62..0161d94be64 100644 --- a/gcc/flow.c +++ b/gcc/flow.c @@ -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) diff --git a/gcc/function.c b/gcc/function.c index 4645f5af7cc..48018cff6f5 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -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; diff --git a/gcc/output.h b/gcc/output.h index 06d5204c7f3..83ec167f298 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -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; diff --git a/gcc/reorg.c b/gcc/reorg.c index 007d92eca3d..d4c7778570c 100644 --- a/gcc/reorg.c +++ b/gcc/reorg.c @@ -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); } -- 2.43.5