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]

i386 PIC improvement for static functions.


This patch allows the compiler to detect situations which don't require
the pic register to be loaded for static functions.  It works by having
expand_expr mark functions whose address has been used.  Static functions
which have not been marked by expand_expr don't need to load the pic
register since they are only called by other functions which are in the
same file (and hence share the same global table pointer).

ChangeLog:

Sat Jun 20 16:18:00 EDT 1998  John Wehle  (john@feith.com)

	* toplev.c (rest_of_compilation): Defer static functions
	when optimizing for PIC.
	* tree.h (struct tree_common): Add address_load_flag.
	(TREE_ADDRESS_LOAD): New macro.
	* print-tree.c (print_node): Handle TREE_ADDRESS_LOAD.
	* expr.c (expand_expr): Set TREE_ADDRESS_LOAD if it's a function.
	* i386.c (need_to_load_pic_register): New function.
	(asm_output_function_prefix, ix86_prologue,
	ix86_can_use_return_insn_p, ix86_epilogue): Use it.

Enjoy!

-- John Wehle
------------------8<------------------------8<------------------------
*** gcc/toplev.c.ORIGINAL	Mon Jun  8 08:43:20 1998
--- gcc/toplev.c	Sun Jun 14 20:20:47 1998
***************
*** 3028,3034 ****
  	 compile it by itself, defer decision till end of compilation.
  	 finish_compilation will call rest_of_compilation again
  	 for those functions that need to be output.  Also defer those
! 	 functions that we are supposed to defer.  We cannot defer
  	 functions containing nested functions since the nested function
  	 data is in our non-saved obstack.  We cannot defer nested
  	 functions for the same reason.  */
--- 3028,3036 ----
  	 compile it by itself, defer decision till end of compilation.
  	 finish_compilation will call rest_of_compilation again
  	 for those functions that need to be output.  Also defer those
! 	 functions that we are supposed to defer.  We defer static
! 	 functions when optimizing for PIC so that the function
! 	 prolog can optimize loading the PIC register.  We cannot defer
  	 functions containing nested functions since the nested function
  	 data is in our non-saved obstack.  We cannot defer nested
  	 functions for the same reason.  */
***************
*** 3048,3053 ****
--- 3050,3056 ----
        if (! current_function_contains_functions
  	  && ! decl_function_context (decl)
  	  && (DECL_DEFER_OUTPUT (decl)
+ 	      || (! TREE_PUBLIC (decl) && optimize && flag_pic)
  	      || (DECL_INLINE (decl)
  		  && ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl)
  		       && ! flag_keep_inline_functions)
*** gcc/tree.h.ORIGINAL	Mon Jun  8 08:43:21 1998
--- gcc/tree.h	Thu Jun 18 00:06:26 1998
***************
*** 169,174 ****
--- 169,175 ----
    unsigned constant_flag : 1;
    unsigned permanent_flag : 1;
    unsigned addressable_flag : 1;
+   unsigned address_load_flag : 1;
    unsigned volatile_flag : 1;
    unsigned readonly_flag : 1;
    unsigned unsigned_flag : 1;
***************
*** 188,194 ****
    unsigned lang_flag_4 : 1;
    unsigned lang_flag_5 : 1;
    unsigned lang_flag_6 : 1;
!   /* There is room for three more flags.  */
  };
  
  /* The following table lists the uses of each of the above flags and
--- 189,195 ----
    unsigned lang_flag_4 : 1;
    unsigned lang_flag_5 : 1;
    unsigned lang_flag_6 : 1;
!   /* There is room for two more flags.  */
  };
  
  /* The following table lists the uses of each of the above flags and
***************
*** 201,206 ****
--- 202,212 ----
     	   VAR_DECL, FUNCTION_DECL, CONSTRUCTOR, LABEL_DECL, ..._TYPE
  	   IDENTIFIER_NODE
  
+    address_load_flag:
+ 
+        TREE_ADDRESS_LOAD in
+    	   FUNCTION_DECL
+ 
     static_flag:
  
         TREE_STATIC in
***************
*** 415,420 ****
--- 421,430 ----
     In IDENTIFIER_NODEs, this means that some extern decl for this name
     had its address taken.  That matters for inline functions.  */
  #define TREE_ADDRESSABLE(NODE) ((NODE)->common.addressable_flag)
+ 
+ /* In a FUNCTION_DECL, nonzero means its address has been loaded so
+    assume that it can be called from other modules even if !TREE_PUBLIC. */
+ #define TREE_ADDRESS_LOAD(NODE) ((NODE)->common.address_load_flag)
  
  /* In a VAR_DECL, nonzero means allocate static storage.
     In a FUNCTION_DECL, nonzero if function has been defined.
*** gcc/print-tree.c.ORIGINAL	Wed Apr  8 10:03:45 1998
--- gcc/print-tree.c	Thu Jun 18 01:01:57 1998
***************
*** 293,298 ****
--- 293,300 ----
      fputs (" constant", file);
    if (TREE_ADDRESSABLE (node))
      fputs (" addressable", file);
+   if (TREE_ADDRESS_LOAD (node))
+     fputs (" address_load", file);
    if (TREE_THIS_VOLATILE (node))
      fputs (" volatile", file);
    if (TREE_UNSIGNED (node))
*** gcc/expr.c.ORIGINAL	Mon Jun  8 08:43:15 1998
--- gcc/expr.c	Thu Jun 18 23:45:45 1998
***************
*** 5140,5145 ****
--- 5140,5151 ----
  	  TREE_USED (exp) = 1;
  	}
  
+       /* Mark function address as being loaded. */
+       if (code == FUNCTION_DECL)
+ 	{
+ 	  TREE_ADDRESS_LOAD (exp) = 1;
+ 	}
+ 
        /* Show we haven't gotten RTL for this yet.  */
        temp = 0;
  
*** gcc/config/i386/i386.c.ORIGINAL	Fri Jun 12 22:52:54 1998
--- gcc/config/i386/i386.c	Sat Jun 20 01:19:52 1998
***************
*** 1899,1904 ****
--- 1899,1922 ----
  static char pic_label_name [256];
  static int pic_label_no = 0;
  
+ /* Indicate if the pic register needs to be loaded.  A static function
+    whose address has never been assigned to a variable does not need to
+    load the pic register since it will already have the correct value.
+    Detecting this situation requires that processing the static function
+    be deferred until the end which is only done when optimizing.  Assume
+    the worst case when not optimizing. */
+ 
+ static int
+ need_to_load_pic_register()
+ {
+ 
+   return flag_pic && (current_function_uses_pic_offset_table
+ 		    || current_function_uses_const_pool)
+ 		  && (TREE_PUBLIC (current_function_decl)
+ 		    || TREE_ADDRESS_LOAD(current_function_decl)
+ 		    || !optimize);
+ }
+ 
  /* This function generates code for -fpic that loads %ebx with
     the return address of the caller and then returns.  */
  
***************
*** 1908,1915 ****
       char *name;
  {
    rtx xops[2];
!   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
! 				  || current_function_uses_const_pool);
    xops[0] = pic_offset_table_rtx;
    xops[1] = stack_pointer_rtx;
  
--- 1926,1932 ----
       char *name;
  {
    rtx xops[2];
!   int pic_reg_used = need_to_load_pic_register();
    xops[0] = pic_offset_table_rtx;
    xops[1] = stack_pointer_rtx;
  
***************
*** 2037,2044 ****
    register int regno;
    int limit;
    rtx xops[4];
!   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
! 				  || current_function_uses_const_pool);
    long tsize = get_frame_size ();
    rtx insn;
    int cfa_offset = INCOMING_FRAME_SP_OFFSET, cfa_store_offset = cfa_offset;
--- 2054,2060 ----
    register int regno;
    int limit;
    rtx xops[4];
!   int pic_reg_used = need_to_load_pic_register();
    long tsize = get_frame_size ();
    rtx insn;
    int cfa_offset = INCOMING_FRAME_SP_OFFSET, cfa_store_offset = cfa_offset;
***************
*** 2204,2211 ****
    int nregs = 0;
    int reglimit = (frame_pointer_needed
  		  ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
!   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
! 				  || current_function_uses_const_pool);
  
  #ifdef NON_SAVING_SETJMP
    if (NON_SAVING_SETJMP && current_function_calls_setjmp)
--- 2220,2226 ----
    int nregs = 0;
    int reglimit = (frame_pointer_needed
  		  ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
!   int pic_reg_used = need_to_load_pic_register();
  
  #ifdef NON_SAVING_SETJMP
    if (NON_SAVING_SETJMP && current_function_calls_setjmp)
***************
*** 2251,2258 ****
    register int nregs, limit;
    int offset;
    rtx xops[3];
!   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
! 				  || current_function_uses_const_pool);
    long tsize = get_frame_size ();
  
    /* Compute the number of registers to pop */
--- 2266,2272 ----
    register int nregs, limit;
    int offset;
    rtx xops[3];
!   int pic_reg_used = need_to_load_pic_register();
    long tsize = get_frame_size ();
  
    /* Compute the number of registers to pop */
-------------------------------------------------------------------------
|   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]