This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch to improve x86 prologue (Version 3)
- To: rth at cygnus dot com
- Subject: Patch to improve x86 prologue (Version 3)
- From: John Wehle <john at feith dot com>
- Date: Sun, 18 Apr 1999 00:47:22 -0400 (EDT)
- Cc: egcs-patches at egcs dot cygnus dot com
[ This version also replaces leaf_function with
current_function_only_uses_leaf_regs. It passes bootstrap and make
check on x86 FreeBSD 3.1. It has also been bootstrapped on SPARC
Solaris 2.5.1. ]
This patch avoids unnecessary aligning of the stack by the prologue.
The effect of this patch can be seen by compiling:
int a;
void
func(int b)
{
a = b;
}
with -O2 -S.
ChangeLog:
Sat Apr 17 20:07:34 EDT 1999 John Wehle (john@feith.com)
* output.h (current_function_is_leaf,
current_function_uses_only_leaf_regs): Declare.
* function.c (current_function_is_leaf,
current_function_uses_only_leaf_regs): Define.
(init_function_start): Initialize current_function_is_leaf
and current_function_uses_only_leaf_regs.
* final.c (leaf_function): Don't define.
(final_start_function): Replace uses of leaf_function with
current_function_uses_only_leaf_regs.
* toplev.c (rest_of_compilation): Set current_function_is_leaf
prior to invoking local register allocation.
(rest_of_compilation): Replace uses of leaf_function with
current_function_uses_only_leaf_regs.
* dbxout.c (dbxout_symbol, dbxout_parms): Likewise.
* dwarf2out.c (add_location_or_const_vaule_attribute): Likewise.
* dwarfout.c (add_location_or_const_value_attribute): Likewise.
* sdbout.c (sdbout_symbol): Likewise.
* sparc.h (FUNCTION_PROLOGUE, FUNCTION_EPILOGUE): Likewise.
* sparc.c (eligible_for_epilogue_delay, output_return,
sparc_return_peephole_ok): Likewise.
* sparc.md (leaf_function attribute, untyped_return): Likewise.
* i386.c (ix86_compute_frame_size): Don't align the stack
for leaf functions which don't allocate any stack slots.
* tm.texi: Update documentation.
Enjoy!
-- John Wehle
------------------8<------------------------8<------------------------
*** gcc/output.h.ORIGINAL Tue Apr 13 22:39:33 1999
--- gcc/output.h Sat Apr 17 14:35:09 1999
*************** extern int current_function_has_nonlocal
*** 383,393 ****
--- 383,406 ----
extern int current_function_contains_functions;
+ /* Nonzero if function being compiled doesn't contain any calls
+ (ignoring the prologue and epilogue). This is set prior to
+ local register allocation and is valid for the remaining
+ compiler passes. */
+
+ extern int current_function_is_leaf;
+
/* 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 function being compiled is a leaf function which only
+ uses leaf registers. This is valid after reload (specifically after
+ sched2) and is useful only if the port defines LEAF_REGISTERS. */
+
+ extern int current_function_uses_only_leaf_regs;
/* Nonzero if the function being compiled issues a computed jump. */
*** gcc/function.c.ORIGINAL Tue Apr 13 22:39:32 1999
--- gcc/function.c Sat Apr 17 14:35:45 1999
*************** int current_function_has_nonlocal_goto;
*** 140,151 ****
--- 140,164 ----
int current_function_contains_functions;
+ /* Nonzero if function being compiled doesn't contain any calls
+ (ignoring the prologue and epilogue). This is set prior to
+ local register allocation and is valid for the remaining
+ compiler passes. */
+
+ int current_function_is_leaf;
+
/* 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 function being compiled is a leaf function which only
+ uses leaf registers. This is valid after reload (specifically after
+ sched2) and is useful only if the port defines LEAF_REGISTERS. */
+
+ int current_function_uses_only_leaf_regs;
+
/* Nonzero if the function being compiled issues a computed jump. */
int current_function_has_computed_jump;
*************** init_function_start (subr, filename, lin
*** 5897,5903 ****
--- 5910,5918 ----
current_function_has_nonlocal_label = 0;
current_function_has_nonlocal_goto = 0;
current_function_contains_functions = 0;
+ current_function_is_leaf = 0;
current_function_sp_is_unchanging = 0;
+ current_function_uses_only_leaf_regs = 0;
current_function_has_computed_jump = 0;
current_function_is_thunk = 0;
*** gcc/final.c.ORIGINAL Mon Mar 22 02:56:06 1999
--- gcc/final.c Sat Apr 17 14:25:06 1999
*************** Boston, MA 02111-1307, USA. */
*** 131,141 ****
#define JUMP_TABLES_IN_TEXT_SECTION 0
#endif
- /* Nonzero means this function is a leaf function, with no function calls.
- This variable exists to be examined in FUNCTION_PROLOGUE
- and FUNCTION_EPILOGUE. Always zero, unless set by some action. */
- int leaf_function;
-
/* Last insn processed by final_scan_insn. */
static rtx debug_insn = 0;
--- 131,136 ----
*************** final_start_function (first, file, optim
*** 1634,1640 ****
output_source_line (file, first);
#ifdef LEAF_REG_REMAP
! if (leaf_function)
leaf_renumber_regs (first);
#endif
--- 1629,1635 ----
output_source_line (file, first);
#ifdef LEAF_REG_REMAP
! if (current_function_uses_only_leaf_regs)
leaf_renumber_regs (first);
#endif
*** gcc/toplev.c.ORIGINAL Sat Apr 17 13:45:22 1999
--- gcc/toplev.c Sat Apr 17 14:28:00 1999
*************** rest_of_compilation (decl)
*** 4089,4094 ****
--- 4089,4099 ----
}
}
+ /* Determine if the current function is a leaf before running reload
+ since this can impact optimizations done by the prologue and
+ epilogue thus changing register elimination offsets. */
+ current_function_is_leaf = leaf_function_p ();
+
/* Unless we did stupid register allocation,
allocate pseudo-regs that are used only within 1 basic block.
*************** rest_of_compilation (decl)
*** 4235,4243 ****
}
#ifdef LEAF_REGISTERS
- leaf_function = 0;
if (optimize > 0 && only_leaf_regs_used () && leaf_function_p ())
! leaf_function = 1;
#endif
/* One more attempt to remove jumps to .+1
--- 4240,4247 ----
}
#ifdef LEAF_REGISTERS
if (optimize > 0 && only_leaf_regs_used () && leaf_function_p ())
! current_function_uses_only_leaf_regs = 1;
#endif
/* One more attempt to remove jumps to .+1
*** gcc/dbxout.c.ORIGINAL Fri Mar 19 03:50:00 1999
--- gcc/dbxout.c Sat Apr 17 13:55:45 1999
*************** dbxout_symbol (decl, local)
*** 1937,1943 ****
DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
! if (leaf_function)
leaf_renumber_regs_insn (DECL_RTL (decl));
#endif
--- 1937,1943 ----
DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
! if (current_function_uses_only_leaf_regs)
leaf_renumber_regs_insn (DECL_RTL (decl));
#endif
*************** dbxout_parms (parms)
*** 2259,2265 ****
= eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX);
DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
! if (leaf_function)
{
leaf_renumber_regs_insn (DECL_INCOMING_RTL (parms));
leaf_renumber_regs_insn (DECL_RTL (parms));
--- 2259,2265 ----
= eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX);
DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
! if (current_function_uses_only_leaf_regs)
{
leaf_renumber_regs_insn (DECL_INCOMING_RTL (parms));
leaf_renumber_regs_insn (DECL_RTL (parms));
*** gcc/dwarf2out.c.ORIGINAL Wed Mar 31 22:22:17 1999
--- gcc/dwarf2out.c Sat Apr 17 13:55:51 1999
*************** add_location_or_const_value_attribute (d
*** 7207,7213 ****
rtl = eliminate_regs (rtl, 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
! if (leaf_function)
leaf_renumber_regs_insn (rtl);
#endif
--- 7207,7213 ----
rtl = eliminate_regs (rtl, 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
! if (current_function_uses_only_leaf_regs)
leaf_renumber_regs_insn (rtl);
#endif
*** gcc/dwarfout.c.ORIGINAL Sun Mar 21 07:14:09 1999
--- gcc/dwarfout.c Sat Apr 17 13:56:02 1999
*************** location_or_const_value_attribute (decl)
*** 2421,2427 ****
rtl = eliminate_regs (rtl, 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
! if (leaf_function)
leaf_renumber_regs_insn (rtl);
#endif
--- 2421,2427 ----
rtl = eliminate_regs (rtl, 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
! if (current_function_uses_only_leaf_regs)
leaf_renumber_regs_insn (rtl);
#endif
*** gcc/sdbout.c.ORIGINAL Wed Mar 31 22:22:33 1999
--- gcc/sdbout.c Sat Apr 17 13:56:31 1999
*************** sdbout_symbol (decl, local)
*** 811,817 ****
DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
! if (leaf_function)
leaf_renumber_regs_insn (DECL_RTL (decl));
#endif
value = DECL_RTL (decl);
--- 811,817 ----
DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
! if (current_function_uses_only_leaf_regs)
leaf_renumber_regs_insn (DECL_RTL (decl));
#endif
value = DECL_RTL (decl);
*** gcc/config/sparc/sparc.h.ORIGINAL Sat Mar 20 14:31:37 1999
--- gcc/config/sparc/sparc.h Sat Apr 17 14:12:24 1999
*************** do { \
*** 1838,1847 ****
to do a "save" insn. The decision about whether or not
to do this is made in regclass.c. */
- extern int leaf_function;
#define FUNCTION_PROLOGUE(FILE, SIZE) \
(TARGET_FLAT ? sparc_flat_output_function_prologue (FILE, (int)SIZE) \
! : output_function_prologue (FILE, (int)SIZE, leaf_function))
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry.
--- 1838,1847 ----
to do a "save" insn. The decision about whether or not
to do this is made in regclass.c. */
#define FUNCTION_PROLOGUE(FILE, SIZE) \
(TARGET_FLAT ? sparc_flat_output_function_prologue (FILE, (int)SIZE) \
! : output_function_prologue (FILE, (int)SIZE, \
! current_function_uses_only_leaf_regs))
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry.
*************** extern union tree_node *current_function
*** 2216,2222 ****
#define FUNCTION_EPILOGUE(FILE, SIZE) \
(TARGET_FLAT ? sparc_flat_output_function_epilogue (FILE, (int)SIZE) \
! : output_function_epilogue (FILE, (int)SIZE, leaf_function))
#define DELAY_SLOTS_FOR_EPILOGUE \
(TARGET_FLAT ? sparc_flat_epilogue_delay_slots () : 1)
--- 2216,2223 ----
#define FUNCTION_EPILOGUE(FILE, SIZE) \
(TARGET_FLAT ? sparc_flat_output_function_epilogue (FILE, (int)SIZE) \
! : output_function_epilogue (FILE, (int)SIZE, \
! current_function_uses_only_leaf_regs))
#define DELAY_SLOTS_FOR_EPILOGUE \
(TARGET_FLAT ? sparc_flat_epilogue_delay_slots () : 1)
*** gcc/config/sparc/sparc.c.ORIGINAL Sun Mar 7 00:46:27 1999
--- gcc/config/sparc/sparc.c Sat Apr 17 14:13:36 1999
*************** eligible_for_epilogue_delay (trial, slot
*** 2230,2236 ****
/* In the case of a true leaf function, anything can go into the delay slot.
A delay slot only exists however if the frame size is zero, otherwise
we will put an insn to adjust the stack after the return. */
! if (leaf_function)
{
if (leaf_return_peephole_ok ())
return ((get_attr_in_uncond_branch_delay (trial)
--- 2230,2236 ----
/* In the case of a true leaf function, anything can go into the delay slot.
A delay slot only exists however if the frame size is zero, otherwise
we will put an insn to adjust the stack after the return. */
! if (current_function_uses_only_leaf_regs)
{
if (leaf_return_peephole_ok ())
return ((get_attr_in_uncond_branch_delay (trial)
*************** output_return (operands)
*** 4686,4692 ****
operands[0] = leaf_label;
return "b%* %l0%(";
}
! else if (leaf_function)
{
/* No delay slot in a leaf function. */
if (delay)
--- 4686,4692 ----
operands[0] = leaf_label;
return "b%* %l0%(";
}
! else if (current_function_uses_only_leaf_regs)
{
/* No delay slot in a leaf function. */
if (delay)
*************** sparc_return_peephole_ok (dest, src)
*** 7524,7530 ****
{
if (! TARGET_V9)
return 0;
! if (leaf_function)
return 0;
if (GET_CODE (src) != CONST_INT
&& (GET_CODE (src) != REG || ! IN_OR_GLOBAL_P (src)))
--- 7524,7530 ----
{
if (! TARGET_V9)
return 0;
! if (current_function_uses_only_leaf_regs)
return 0;
if (GET_CODE (src) != CONST_INT
&& (GET_CODE (src) != REG || ! IN_OR_GLOBAL_P (src)))
*** gcc/config/sparc/sparc.md.ORIGINAL Sun Mar 7 00:46:30 1999
--- gcc/config/sparc/sparc.md Sat Apr 17 14:15:06 1999
***************
*** 159,165 ****
[(eq_attr "in_call_delay" "true") (nil) (nil)])
(define_attr "leaf_function" "false,true"
! (const (symbol_ref "leaf_function")))
(define_attr "in_return_delay" "false,true"
(if_then_else (and (and (and (eq_attr "type" "move,load,sload,store,binary,ialu")
--- 159,165 ----
[(eq_attr "in_call_delay" "true") (nil) (nil)])
(define_attr "leaf_function" "false,true"
! (const (symbol_ref "current_function_uses_only_leaf_regs")))
(define_attr "in_return_delay" "false,true"
(if_then_else (and (and (and (eq_attr "type" "move,load,sload,store,binary,ialu")
***************
*** 7618,7624 ****
if (! TARGET_ARCH64)
{
! rtx rtnreg = gen_rtx_REG (SImode, (leaf_function ? 15 : 31));
rtx value = gen_reg_rtx (SImode);
/* Fetch the instruction where we will return to and see if it's an unimp
--- 7618,7625 ----
if (! TARGET_ARCH64)
{
! rtx rtnreg = gen_rtx_REG (SImode, (current_function_uses_only_leaf_regs
! ? 15 : 31));
rtx value = gen_reg_rtx (SImode);
/* Fetch the instruction where we will return to and see if it's an unimp
*** gcc/config/i386/i386.c.ORIGINAL Sat Apr 17 13:46:05 1999
--- gcc/config/i386/i386.c Sat Apr 17 14:26:56 1999
*************** ix86_compute_frame_size (size, nregs_on_
*** 1968,1973 ****
--- 1968,1978 ----
if (padding < (((offset + preferred_alignment - 1)
& -preferred_alignment) - offset))
padding += preferred_alignment;
+
+ /* Don't bother aligning the stack of a leaf function
+ which doesn't allocate any stack slots. */
+ if (size == 0 && current_function_is_leaf)
+ padding = 0;
}
#endif
*** gcc/tm.texi.ORIGINAL Thu Apr 8 04:18:24 1999
--- gcc/tm.texi Sat Apr 17 14:52:04 1999
*************** treatment of leaf functions, and registe
*** 1642,1653 ****
this.
@end table
! @findex leaf_function
Normally, @code{FUNCTION_PROLOGUE} and @code{FUNCTION_EPILOGUE} must
! treat leaf functions specially. It can test the C variable
! @code{leaf_function} which is nonzero for leaf functions. (The variable
! @code{leaf_function} is defined only if @code{LEAF_REGISTERS} is
! defined.)
@c changed this to fix overfull. ALSO: why the "it" at the beginning
@c of the next paragraph?! --mew 2feb93
--- 1642,1658 ----
this.
@end table
! @findex current_function_is_leaf
! @findex current_function_uses_only_leaf_regs
Normally, @code{FUNCTION_PROLOGUE} and @code{FUNCTION_EPILOGUE} must
! treat leaf functions specially. They can test the C variable
! @code{current_function_is_leaf} which is nonzero for leaf functions.
! @code{current_function_is_leaf} is set prior to local register allocation
! and is valid for the remaining compiler passes. They can also test the C
! variable @code{current_function_uses_only_leaf_regs} which is nonzero for
! leaf functions which only use leaf registers.
! @code{current_function_uses_only_leaf_regs} is valid after reload and is
! only useful if @code{LEAF_REGISTERS} is defined.
@c changed this to fix overfull. ALSO: why the "it" at the beginning
@c of the next paragraph?! --mew 2feb93
*************** argument lists of the function. @xref{S
*** 3296,3302 ****
Normally, it is necessary for the macros @code{FUNCTION_PROLOGUE} and
@code{FUNCTION_EPILOGUE} to treat leaf functions specially. The C
! variable @code{leaf_function} is nonzero for such a function.
@findex EXIT_IGNORE_STACK
@item EXIT_IGNORE_STACK
--- 3301,3307 ----
Normally, it is necessary for the macros @code{FUNCTION_PROLOGUE} and
@code{FUNCTION_EPILOGUE} to treat leaf functions specially. The C
! variable @code{current_function_is_leaf} is nonzero for such a function.
@findex EXIT_IGNORE_STACK
@item EXIT_IGNORE_STACK
*************** is wanted, the macro can refer to the va
*** 3346,3353 ****
a function that needs a frame pointer.
Normally, @code{FUNCTION_PROLOGUE} and @code{FUNCTION_EPILOGUE} must
! treat leaf functions specially. The C variable @code{leaf_function} is
! nonzero for such a function. @xref{Leaf Functions}.
On some machines, some functions pop their arguments on exit while
others leave that for the caller to do. For example, the 68020 when
--- 3351,3358 ----
a function that needs a frame pointer.
Normally, @code{FUNCTION_PROLOGUE} and @code{FUNCTION_EPILOGUE} must
! treat leaf functions specially. The C variable @code{current_function_is_leaf}
! is nonzero for such a function. @xref{Leaf Functions}.
On some machines, some functions pop their arguments on exit while
others leave that for the caller to do. For example, the 68020 when
-------------------------------------------------------------------------
| Feith Systems | Voice: 1-215-646-8000 | Email: john@feith.com |
| John Wehle | Fax: 1-215-540-5495 | |
-------------------------------------------------------------------------