This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch to improve x86 prologue (Version 3)


[ 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  |                         |
-------------------------------------------------------------------------



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]