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]
Other format: [Raw text]

[tree-ssa] Reorganize expansion of nested functions


Hi,
I need this patch primarily to get CFG transparent expansion, but I think it is
usefull at it's own.
At very minimum it happens to fix gcc.dg/20020425-1.c , but I dind't looked in
detail why :)  The problem of nested functions is that they needs to be compiled
after the outer function has been optimized and before it has been expanded.
This makes it dificult to keep CFG transparent without actually allowing
multiple CFGs at a time (that I plan to do in mid term too, but don't want to
do it before the merge as it will bring a lot of noise).

The patch makes the analysis done at expansion time to happen at trees, so
compilation can be deferred after completing the body.  It has disadvantage of
not taking into account optimizations that can happen on nested function and
theoretically can elliminate indirect calls and nonlocal gotos I am looking
for, but it can be quite rare.  On the other hand, we can make the information
readilly available for tree optimizers and let cgraph code to control expansion
of nested functions to get some code improvements.

Bootstrapped/regtested i686-pc-gnu-linux, OK?
 
2004-02-01  Jan Hubicka  <jh@suse.cz>
	* function.c (notice_parameter_referenced_by_nested_function): New
	function.
	* function.h (notice_parameter_referenced_by_nested_function): Declare.
	* gimple-low.c: Include cgraph.h
	(expand_used_vars): Do not expand nested function.s
	(examine_nested_function_1): New static function.
	(examine_nested_functions, expand_nested_functions): New global
	functions.
	* tree-flow.h (examine_nested_functions, expand_nested_functions):
	Declare.
	* tree-optimize.c (tree_rest_of_compilation): Expand nested function after
	expanding the origin.

Index: function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.374.2.38
diff -c -3 -p -r1.374.2.38 function.c
*** function.c	30 Jan 2004 13:13:56 -0000	1.374.2.38
--- function.c	1 Feb 2004 00:18:34 -0000
*************** use_return_register (void)
*** 6861,6866 ****
--- 6861,6876 ----
    diddle_return_value (do_use_return_reg, NULL);
  }
  
+ /* PARAM is function parameter referenced by nested function, prepare to
+    produce correct code in that case.  */
+ void
+ notice_parameter_referenced_by_nested_function (tree param ATTRIBUTE_UNUSED)
+ {
+ #ifdef NEED_SEPARATE_AP
+   get_arg_pointer_save_area (cfun);
+ #endif
+ }
+ 
  static GTY(()) rtx initial_trampoline;
  
  /* Generate RTL for the end of the current function.  */
Index: function.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.h,v
retrieving revision 1.83.2.25
diff -c -3 -p -r1.83.2.25 function.h
*** function.h	30 Jan 2004 13:13:56 -0000	1.83.2.25
--- function.h	1 Feb 2004 00:18:34 -0000
*************** extern const char *current_function_name
*** 673,676 ****
--- 673,678 ----
  /* Called once, at initialization, to initialize function.c.  */
  extern void init_function_once (void);
  
+ extern void notice_parameter_referenced_by_nested_function (tree param);
+ 
  #endif  /* GCC_FUNCTION_H */
Index: gimple-low.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/gimple-low.c,v
retrieving revision 1.1.4.17
diff -c -3 -p -r1.1.4.17 gimple-low.c
*** gimple-low.c	12 Jan 2004 23:39:31 -0000	1.1.4.17
--- gimple-low.c	1 Feb 2004 00:18:34 -0000
*************** Software Foundation, 59 Temple Place - S
*** 41,46 ****
--- 41,47 ----
  #include "expr.h"
  #include "toplev.h"
  #include "tree-pass.h"
+ #include "cgraph.h"
  
  struct lower_data
  {
*************** expand_used_vars (void)
*** 446,452 ****
    cfun->unexpanded_var_list = nreverse (cfun->unexpanded_var_list);
  
    for (cell = cfun->unexpanded_var_list; cell; cell = TREE_CHAIN (cell))
!     expand_var (TREE_VALUE (cell));
  
    cfun->unexpanded_var_list = NULL_TREE;
  }
--- 447,547 ----
    cfun->unexpanded_var_list = nreverse (cfun->unexpanded_var_list);
  
    for (cell = cfun->unexpanded_var_list; cell; cell = TREE_CHAIN (cell))
!     if (TREE_CODE (TREE_VALUE (cell)) != FUNCTION_DECL)
!       expand_var (TREE_VALUE (cell));
! }
! 
! /* Examine nested functions and work out whether we need an trampolines and
!    nonlocal goto receivers.  Used via walk_tree,  DATA points to function
!    being examined.  */
! static tree
! examine_nested_functions_1 (tree * tp, int *walk_subtrees, void *data)
! {
!   tree t = *tp;
!   tree decl;
! 
!   switch (TREE_CODE (t))
!     {
!     case PARM_DECL:
!       if (decl_function_context (t) == current_function_decl)
! 	{
! 	  DECL_NONLOCAL (t) = 1;
! 	  notice_parameter_referenced_by_nested_function (t);
! 	}
!     case VAR_DECL:
!       if (decl_function_context (t) == current_function_decl)
! 	DECL_NONLOCAL (t) = 1;
!       break;
!     case LABEL_DECL:
!       if (decl_function_context (t) == current_function_decl)
! 	cfun->has_nonlocal_label = 1;
!       break;
! 
!     case ADDR_EXPR:
!       decl = get_base_symbol (TREE_OPERAND (t, 0));
!       if (decl && TREE_CODE (decl) == FUNCTION_DECL)
! 	{
! 	  struct cgraph_node *node = cgraph_node (decl);
! 
! 	  if (node->origin
! 	      && node->origin == cgraph_node (current_function_decl))
! 	    trampoline_address (node->decl);
! 	}
!       *walk_subtrees = 0;
!       break;
! 
!     case CALL_EXPR:
!       {
! 	tree decl = get_callee_fndecl (*tp);
! 
! 	/* Do not record direct calls as taking address.  */
! 	if (decl && TREE_CODE (decl) == FUNCTION_DECL)
! 	  {
! 	    walk_tree (&TREE_OPERAND (*tp, 1), examine_nested_functions_1,
! 		       data, NULL);
! 	    *walk_subtrees = 0;
! 	  }
! 	break;
!       }
! 
!     default:
!       /* Save some cycles by not walking types and declaration as we
!          won't find anything useful there anyway.  */
!       if (DECL_P (*tp) || TYPE_P (*tp))
! 	{
! 	  *walk_subtrees = 0;
! 	  break;
! 	}
!       break;
!     }
! 
!   return NULL;
! }
! 
! /* Look into nested functions and initialize templates and nonlocal goto
!    receivers.  */
! void
! examine_nested_functions (void)
! {
!   tree cell;
! 
!   for (cell = cfun->unexpanded_var_list; cell; cell = TREE_CHAIN (cell))
!     if (TREE_CODE (TREE_VALUE (cell)) == FUNCTION_DECL)
!       {
! 	walk_tree (&DECL_SAVED_TREE (TREE_VALUE (cell)),
! 		   examine_nested_functions_1, TREE_VALUE (cell), NULL);
!       }
! }
! 
! /* Expand all nested functions.  */
! void
! expand_nested_functions (void)
! {
!   tree cell;
! 
!   for (cell = cfun->unexpanded_var_list; cell; cell = TREE_CHAIN (cell))
!     if (TREE_CODE (TREE_VALUE (cell)) == FUNCTION_DECL)
!       expand_var (TREE_VALUE (cell));
  
    cfun->unexpanded_var_list = NULL_TREE;
  }
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.184
diff -c -3 -p -r1.1.4.184 tree-flow.h
*** tree-flow.h	19 Jan 2004 23:21:42 -0000	1.1.4.184
--- tree-flow.h	1 Feb 2004 00:18:34 -0000
*************** extern void expand_used_vars (void);
*** 494,499 ****
--- 494,501 ----
  extern void remove_useless_vars (void);
  extern void record_vars (tree);
  extern bool block_may_fallthru (tree block);
+ extern void expand_nested_functions (void);
+ extern void examine_nested_functions (void);
  
  /* In tree-ssa.c  */
  extern void init_tree_ssa (void);
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 1.1.4.113
diff -c -3 -p -r1.1.4.113 tree-optimize.c
*** tree-optimize.c	19 Jan 2004 19:14:20 -0000	1.1.4.113
--- tree-optimize.c	1 Feb 2004 00:18:34 -0000
*************** tree_rest_of_compilation (tree fndecl, b
*** 516,521 ****
--- 516,523 ----
      walk_tree (&TREE_TYPE (fndecl), set_save_expr_context, fndecl,
  	       NULL);
  
+   examine_nested_functions ();
+ 
    /* Set up parameters and prepare for return, for the function.  */
    expand_function_start (fndecl, 0);
  
*************** tree_rest_of_compilation (tree fndecl, b
*** 554,559 ****
--- 556,563 ----
  
    /* Generate rtl for function exit.  */
    expand_function_end ();
+ 
+   expand_nested_functions ();
  
    /* If this is a nested function, protect the local variables in the stack
       above us from being collected while we're compiling this function.  */


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