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]

[IPA] Kill function body saving code


Hi,
this patch replaces the ugly function body saving hack by constructing full
clone when needed via Razya's new clonning code.  This is important to allow me
to apply inline plan at once (instead of doing it incrementally now) and do
inlining on SSA wihtout having to update those ugly hacks further.

Bootstrapped/regtested i686-pc-gnu-linux, will commit it shortly.
Honza

2005-08-13  Jan Hubicka  <jh@suse.cz>
	* cgraph.c (cgraph_insert_node_to_hashtable): New function.
	* cgraph.h (cgraph_node): Add inline_decl.
	(cgraph_insert_node_to_hashtable): Declare.
	(save_inline_function_body): Declare.
	* cgraphunit.c (verify_cgraph_node): Inline edges might point to inline
	clones.
	(cgraph_preserve_function_body_p): Do not presrve when dump is enabled.
	(cgraph_function_versioning): Update call of tree_function_versioning.
	(save_inline_function_body): New function.
	* function.h (struct function): Kill saved_eh, saved_cfg, saved_args,
	saved_static_chain_decl, saved_blocks and saved-unexpanded_var_list.
	* ipa-inline.c (cgraph_mark_inline_edge): Look for inline clones.
	(cgraph_default_inline_p): Likewise.
	(cgraph_decide_inlining_incrementally): Likewise.
	* tree-inline.c (inline_data): Kill saving_p add update_clones_p.
	(copy_bb): Kill saving; do updating of clones.
	(copy_cfg_body): Kill saving.
	(initialize_inlined-parameters): Likewise.
	(expand_call_inline): Likewise.
	(save_body): Kill.
	(tree_function_versioning): New parameter "update_clones".
	(inlining_p): Kill saving.
	* tree-inline.h (tree_function_versioning): Update prototype.
	* tree-optimize.c (tree_rest_of_compilation): Use clonning instead of saving.

	* java/decl.c (flag_unit_at_a_time): Kill.
Index: cgraph.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.c,v
retrieving revision 1.83
diff -c -3 -p -r1.83 cgraph.c
*** cgraph.c	28 Jul 2005 21:45:24 -0000	1.83
--- cgraph.c	12 Aug 2005 23:06:09 -0000
*************** cgraph_node (tree decl)
*** 213,218 ****
--- 213,231 ----
    return node;
  }
  
+ /* Insert already constructed node into hashtable.  */
+ 
+ void
+ cgraph_insert_node_to_hashtable (struct cgraph_node *node)
+ {
+   struct cgraph_node **slot;
+ 
+   slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, node, INSERT);
+ 
+   gcc_assert (!*slot);
+   *slot = node;
+ }
+ 
  /* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL.  */
  
  static bool
Index: cgraph.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.h,v
retrieving revision 1.64
diff -c -3 -p -r1.64 cgraph.h
*** cgraph.h	1 Aug 2005 07:41:48 -0000	1.64
--- cgraph.h	12 Aug 2005 23:06:09 -0000
*************** struct cgraph_node GTY((chain_next ("%h.
*** 161,166 ****
--- 161,171 ----
    bool externally_visible;
    /* Set for aliases once they got through assemble_alias.  */
    bool alias;
+ 
+   /* In non-unit-at-a-time mode the function body of inline candidates is saved
+      into clone before compiling so the function in original form can be
+      inlined later.  This pointer points to the clone.  */
+   tree inline_decl;
  };
  
  struct cgraph_edge GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller")))
*************** extern GTY(()) struct cgraph_varpool_nod
*** 225,230 ****
--- 230,236 ----
  /* In cgraph.c  */
  void dump_cgraph (FILE *);
  void dump_cgraph_node (FILE *, struct cgraph_node *);
+ void cgraph_insert_node_to_hashtable (struct cgraph_node *node);
  void dump_varpool (FILE *);
  void dump_cgraph_varpool_node (FILE *, struct cgraph_varpool_node *);
  void cgraph_remove_edge (struct cgraph_edge *);
*************** void cgraph_reset_static_var_maps (void)
*** 283,288 ****
--- 289,295 ----
  void init_cgraph (void);
  struct cgraph_node *cgraph_function_versioning (struct cgraph_node *,
                                                  varray_type, varray_type);
+ struct cgraph_node *save_inline_function_body (struct cgraph_node *);
  
  /* In ipa.c  */
  bool cgraph_remove_unreachable_nodes (bool, FILE *);
Index: cgraphunit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraphunit.c,v
retrieving revision 1.126
diff -c -3 -p -r1.126 cgraphunit.c
*** cgraphunit.c	1 Aug 2005 07:42:08 -0000	1.126
--- cgraphunit.c	12 Aug 2005 23:06:09 -0000
*************** verify_cgraph_node (struct cgraph_node *
*** 730,736 ****
  			    debug_generic_stmt (stmt);
  			    error_found = true;
  			  }
! 			if (e->callee->decl != cgraph_node (decl)->decl)
  			  {
  			    error ("edge points to wrong declaration:");
  			    debug_tree (e->callee->decl);
--- 730,737 ----
  			    debug_generic_stmt (stmt);
  			    error_found = true;
  			  }
! 			if (e->callee->decl != cgraph_node (decl)->decl
! 			    && e->inline_failed)
  			  {
  			    error ("edge points to wrong declaration:");
  			    debug_tree (e->callee->decl);
*************** bool
*** 1181,1189 ****
  cgraph_preserve_function_body_p (tree decl)
  {
    struct cgraph_node *node;
-   /* Keep the body; we're going to dump it.  */
-   if (dump_enabled_p (TDI_tree_all))
-     return true;
    if (!cgraph_global_info_ready)
      return (DECL_INLINE (decl) && !flag_really_no_inline);
    /* Look if there is any clone around.  */
--- 1182,1187 ----
*************** cgraph_copy_node_for_versioning (struct 
*** 1462,1469 ****
  
  struct cgraph_node *
  cgraph_function_versioning (struct cgraph_node *old_version_node,
! 			    varray_type redirect_callers,
! 			    varray_type tree_map)
  {
    tree old_decl = old_version_node->decl;
    struct cgraph_node *new_version_node = NULL;
--- 1460,1467 ----
  
  struct cgraph_node *
  cgraph_function_versioning (struct cgraph_node *old_version_node,
! 			      varray_type redirect_callers,
! 			      varray_type tree_map)
  {
    tree old_decl = old_version_node->decl;
    struct cgraph_node *new_version_node = NULL;
*************** cgraph_function_versioning (struct cgrap
*** 1483,1489 ****
  				     redirect_callers);
  
    /* Copy the OLD_VERSION_NODE function tree to the new version.  */
!   tree_function_versioning (old_decl, new_decl, tree_map);
    /* Update the call_expr on the edges to call the new version node. */
    update_call_expr (new_version_node);
  
--- 1481,1487 ----
  				     redirect_callers);
  
    /* Copy the OLD_VERSION_NODE function tree to the new version.  */
!   tree_function_versioning (old_decl, new_decl, tree_map, false);
    /* Update the call_expr on the edges to call the new version node. */
    update_call_expr (new_version_node);
  
*************** cgraph_function_versioning (struct cgrap
*** 1500,1502 ****
--- 1498,1551 ----
    new_version_node->lowered = true;
    return new_version_node;
  }
+ 
+ /* Produce separate function body for inline clones so the offline copy can be
+    modified without affecting them.  */
+ struct cgraph_node *
+ save_inline_function_body (struct cgraph_node *node)
+ {
+   struct cgraph_node *first_clone;
+ 
+   gcc_assert (node == cgraph_node (node->decl));
+ 
+   /* In non-unit-at-a-time we construct full fledged clone we never output to
+      assembly file.  This clone is pointed out by inline_decl of orginal function
+      and inlining infrastructure knows how to deal with this.  */
+   if (!flag_unit_at_a_time)
+     {
+       struct cgraph_edge *e;
+ 
+       first_clone = cgraph_clone_node (node, node->count, 0, false);
+       first_clone->needed = 0;
+       /* Recursively clone all bodies.  */
+       for (e = first_clone->callees; e; e = e->next_callee)
+ 	if (!e->inline_failed)
+ 	  cgraph_clone_inlined_nodes (e, true);
+     }
+   else
+     first_clone = node->next_clone;
+ 
+   first_clone->decl = copy_node (node->decl);
+   node->next_clone = NULL;
+   if (!flag_unit_at_a_time)
+     node->inline_decl = first_clone->decl;
+   first_clone->prev_clone = NULL;
+   cgraph_insert_node_to_hashtable (first_clone);
+   gcc_assert (first_clone == cgraph_node (first_clone->decl));
+ 
+   /* Copy the OLD_VERSION_NODE function tree to the new version.  */
+   tree_function_versioning (node->decl, first_clone->decl, NULL, true);
+ 
+   DECL_EXTERNAL (first_clone->decl) = 0;
+   DECL_ONE_ONLY (first_clone->decl) = 0;
+   TREE_PUBLIC (first_clone->decl) = 0;
+   DECL_COMDAT (first_clone->decl) = 0;
+ 
+   for (node = first_clone->next_clone; node; node = node->next_clone)
+     node->decl = first_clone->decl;
+ #ifdef ENABLE_CHECKING
+   verify_cgraph_node (first_clone);
+ #endif
+   return first_clone;
+ }
+ 
Index: function.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.h,v
retrieving revision 1.156
diff -c -3 -p -r1.156 function.h
*** function.h	30 Jun 2005 00:47:48 -0000	1.156
--- function.h	12 Aug 2005 23:06:09 -0000
*************** struct expr_status GTY(())
*** 162,186 ****
  struct function GTY(())
  {
    struct eh_status *eh;
-   struct eh_status *saved_eh;
    struct expr_status *expr;
    struct emit_status *emit;
    struct varasm_status *varasm;
  
    /* The control flow graph for this function.  */
    struct control_flow_graph *cfg;
-   struct control_flow_graph *saved_cfg;
    bool after_inlining;
  
-   /* For tree-optimize.c.  */
- 
-   /* Saved tree and arguments during tree optimization.  Used later for
-      inlining */
-   tree saved_args;
-   tree saved_static_chain_decl;
-   tree saved_blocks;
-   tree saved_unexpanded_var_list;
- 
    /* For function.c.  */
  
    /* Points to the FUNCTION_DECL of this function.  */
--- 162,175 ----
Index: ipa-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ipa-inline.c,v
retrieving revision 2.15
diff -c -3 -p -r2.15 ipa-inline.c
*** ipa-inline.c	28 Jul 2005 21:45:25 -0000	2.15
--- ipa-inline.c	12 Aug 2005 23:06:09 -0000
*************** cgraph_mark_inline_edge (struct cgraph_e
*** 154,159 ****
--- 154,162 ----
    int old_insns = 0, new_insns = 0;
    struct cgraph_node *to = NULL, *what;
  
+   if (e->callee->inline_decl)
+     cgraph_redirect_edge_callee (e, cgraph_node (e->callee->inline_decl));
+ 
    gcc_assert (e->inline_failed);
    e->inline_failed = NULL;
  
*************** cgraph_check_inline_limits (struct cgrap
*** 279,299 ****
  bool
  cgraph_default_inline_p (struct cgraph_node *n, const char **reason)
  {
!   if (!DECL_INLINE (n->decl))
      {
        if (reason)
  	*reason = N_("function not inlinable");
        return false;
      }
  
!   if (!DECL_SAVED_TREE (n->decl))
      {
        if (reason)
  	*reason = N_("function body not available");
        return false;
      }
  
!   if (DECL_DECLARED_INLINE_P (n->decl))
      {
        if (n->global.insns >= MAX_INLINE_INSNS_SINGLE)
  	{
--- 282,306 ----
  bool
  cgraph_default_inline_p (struct cgraph_node *n, const char **reason)
  {
!   tree decl = n->decl;
! 
!   if (n->inline_decl)
!     decl = n->inline_decl;
!   if (!DECL_INLINE (decl))
      {
        if (reason)
  	*reason = N_("function not inlinable");
        return false;
      }
  
!   if (!DECL_STRUCT_FUNCTION (decl)->cfg)
      {
        if (reason)
  	*reason = N_("function body not available");
        return false;
      }
  
!   if (DECL_DECLARED_INLINE_P (decl))
      {
        if (n->global.insns >= MAX_INLINE_INSNS_SINGLE)
  	{
*************** cgraph_decide_inlining_incrementally (st
*** 1031,1037 ****
          && !cgraph_recursive_inlining_p (node, e->callee, &e->inline_failed)
  	/* ??? It is possible that renaming variable removed the function body
  	   in duplicate_decls. See gcc.c-torture/compile/20011119-2.c  */
! 	&& DECL_SAVED_TREE (e->callee->decl))
        {
          if (dump_file && early)
            fprintf (dump_file, "  Early inlining %s into %s\n",
--- 1038,1044 ----
          && !cgraph_recursive_inlining_p (node, e->callee, &e->inline_failed)
  	/* ??? It is possible that renaming variable removed the function body
  	   in duplicate_decls. See gcc.c-torture/compile/20011119-2.c  */
! 	&& (DECL_SAVED_TREE (e->callee->decl) || e->callee->inline_decl))
        {
          if (dump_file && early)
            fprintf (dump_file, "  Early inlining %s into %s\n",
*************** cgraph_decide_inlining_incrementally (st
*** 1051,1057 ****
  	      || (cgraph_estimate_size_after_inlining (1, e->caller, node)
  	          <= e->caller->global.insns))
  	  && cgraph_check_inline_limits (node, e->callee, &e->inline_failed)
! 	  && DECL_SAVED_TREE (e->callee->decl))
  	{
  	  if (cgraph_default_inline_p (e->callee, &failed_reason))
  	    {
--- 1058,1064 ----
  	      || (cgraph_estimate_size_after_inlining (1, e->caller, node)
  	          <= e->caller->global.insns))
  	  && cgraph_check_inline_limits (node, e->callee, &e->inline_failed)
! 	  && (DECL_SAVED_TREE (e->callee->decl) || e->callee->inline_decl))
  	{
  	  if (cgraph_default_inline_p (e->callee, &failed_reason))
  	    {
Index: tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.210
diff -c -3 -p -r1.210 tree-inline.c
*** tree-inline.c	1 Aug 2005 15:25:28 -0000	1.210
--- tree-inline.c	12 Aug 2005 23:06:10 -0000
*************** typedef struct inline_data
*** 111,119 ****
    tree callee;
    /* FUNCTION_DECL for function being inlined into.  */
    tree caller;
!   /* struct function for function being inlined.  Usually this is the same
!      as DECL_STRUCT_FUNCTION (callee), but can be different if saved_cfg
!      and saved_eh are in use.  */
    struct function *callee_cfun;
    /* The VAR_DECL for the return value.  */
    tree retvar;
--- 111,117 ----
    tree callee;
    /* FUNCTION_DECL for function being inlined into.  */
    tree caller;
!   /* struct function for function being inlined.  */
    struct function *callee_cfun;
    /* The VAR_DECL for the return value.  */
    tree retvar;
*************** typedef struct inline_data
*** 125,134 ****
       distinguish between those two situations.  This flag is true if
       we are cloning, rather than inlining.  */
    bool cloning_p;
-   /* Similarly for saving function body.  */
-   bool saving_p;
    /* Versioning function is slightly different from inlining. */
    bool versioning_p;
    /* Callgraph node of function we are inlining into.  */
    struct cgraph_node *node;
    /* Callgraph node of currently inlined function.  */
--- 123,131 ----
       distinguish between those two situations.  This flag is true if
       we are cloning, rather than inlining.  */
    bool cloning_p;
    /* Versioning function is slightly different from inlining. */
    bool versioning_p;
+   bool update_clones_p;
    /* Callgraph node of function we are inlining into.  */
    struct cgraph_node *node;
    /* Callgraph node of currently inlined function.  */
*************** copy_bb (inline_data *id, basic_block bb
*** 729,774 ****
  	     callgraph edges and update or duplicate them.  */
  	  if (call && (decl = get_callee_fndecl (call)))
  	    {
! 	      if (id->saving_p)
! 		{
! 		  struct cgraph_node *node;
! 		  struct cgraph_edge *edge;
! 
! 		  /* We're saving a copy of the body, so we'll update the
! 		     callgraph nodes in place.  Note that we avoid
! 		     altering the original callgraph node; we begin with
! 		     the first clone.  */
! 		  for (node = id->node->next_clone;
! 		       node;
! 		       node = node->next_clone)
! 		    {
! 		      edge = cgraph_edge (node, orig_stmt);
! 		      gcc_assert (edge);
! 		      edge->call_stmt = stmt;
! 		    }
! 		}
! 	      else
  		{
  		  struct cgraph_edge *edge;
  
  		  /* We're cloning or inlining this body; duplicate the
  		     associate callgraph nodes.  */
! 		  if (!id->versioning_p)
! 		    {
! 		      edge = cgraph_edge (id->current_node, orig_stmt);
! 		      if (edge)
! 			cgraph_clone_edge (edge, id->node, stmt,
! 					   REG_BR_PROB_BASE, 1, true);
! 		    }
  		}
! 	      if (id->versioning_p)
  		{
  		  /* Update the call_expr on the edges from the new version
  		     to its callees. */
  		  struct cgraph_edge *edge;
  		  edge = cgraph_edge (id->node, orig_stmt);
  		  if (edge)
! 		    edge->call_stmt = stmt;
  		}
  	    }
  	  /* If you think we can abort here, you are wrong.
--- 726,758 ----
  	     callgraph edges and update or duplicate them.  */
  	  if (call && (decl = get_callee_fndecl (call)))
  	    {
! 	      if (!id->versioning_p)
  		{
  		  struct cgraph_edge *edge;
  
  		  /* We're cloning or inlining this body; duplicate the
  		     associate callgraph nodes.  */
! 		  edge = cgraph_edge (id->current_node, orig_stmt);
! 		  if (edge)
! 		    cgraph_clone_edge (edge, id->node, stmt,
! 				       REG_BR_PROB_BASE, 1, true);
  		}
! 	      else
  		{
  		  /* Update the call_expr on the edges from the new version
  		     to its callees. */
  		  struct cgraph_edge *edge;
  		  edge = cgraph_edge (id->node, orig_stmt);
  		  if (edge)
! 		    {
! 		      edge->call_stmt = stmt;
! 		      if (id->update_clones_p)
! 			{
! 			  struct cgraph_node *n;
! 			  for (n = id->node->next_clone; n; n = n->next_clone)
! 		            cgraph_edge (n, orig_stmt)->call_stmt = stmt;
! 			}
! 		     }
  		}
  	    }
  	  /* If you think we can abort here, you are wrong.
*************** copy_cfg_body (inline_data * id, gcov_ty
*** 896,902 ****
      (struct function *) ggc_alloc_cleared (sizeof (struct function));
    basic_block bb;
    tree new_fndecl = NULL;
!   bool saving_or_cloning;
    int count_scale, frequency_scale;
  
    if (ENTRY_BLOCK_PTR_FOR_FUNCTION (callee_cfun)->count)
--- 880,886 ----
      (struct function *) ggc_alloc_cleared (sizeof (struct function));
    basic_block bb;
    tree new_fndecl = NULL;
!   bool versioning_or_cloning;
    int count_scale, frequency_scale;
  
    if (ENTRY_BLOCK_PTR_FOR_FUNCTION (callee_cfun)->count)
*************** copy_cfg_body (inline_data * id, gcov_ty
*** 921,944 ****
  
    *cfun_to_copy = *DECL_STRUCT_FUNCTION (callee_fndecl);
  
-   /* If there is a saved_cfg+saved_args lurking in the
-      struct function, a copy of the callee body was saved there, and
-      the 'struct cgraph edge' nodes have been fudged to point into the
-      saved body.  Accordingly, we want to copy that saved body so the
-      callgraph edges will be recognized and cloned properly.  */
-   if (cfun_to_copy->saved_cfg)
-     {
-       cfun_to_copy->cfg = cfun_to_copy->saved_cfg;
-       cfun_to_copy->eh = cfun_to_copy->saved_eh;
-     }
    id->callee_cfun = cfun_to_copy;
  
    /* If saving or cloning a function body, create new basic_block_info
       and label_to_block_maps.  Otherwise, we're duplicating a function
       body for inlining; insert our new blocks and labels into the
       existing varrays.  */
!   saving_or_cloning = (id->saving_p || id->cloning_p || id->versioning_p);
!   if (saving_or_cloning)
      {
        new_cfun =
  	(struct function *) ggc_alloc_cleared (sizeof (struct function));
--- 905,918 ----
  
    *cfun_to_copy = *DECL_STRUCT_FUNCTION (callee_fndecl);
  
    id->callee_cfun = cfun_to_copy;
  
    /* If saving or cloning a function body, create new basic_block_info
       and label_to_block_maps.  Otherwise, we're duplicating a function
       body for inlining; insert our new blocks and labels into the
       existing varrays.  */
!   versioning_or_cloning = (id->cloning_p || id->versioning_p);
!   if (versioning_or_cloning)
      {
        new_cfun =
  	(struct function *) ggc_alloc_cleared (sizeof (struct function));
*************** copy_cfg_body (inline_data * id, gcov_ty
*** 974,980 ****
    /* Duplicate any exception-handling regions.  */
    if (cfun->eh)
      {
!       if (saving_or_cloning)
          init_eh_for_function ();
        id->eh_region_offset = duplicate_eh_regions (cfun_to_copy,
  		     				   remap_decl_1,
--- 948,954 ----
    /* Duplicate any exception-handling regions.  */
    if (cfun->eh)
      {
!       if (versioning_or_cloning)
          init_eh_for_function ();
        id->eh_region_offset = duplicate_eh_regions (cfun_to_copy,
  		     				   remap_decl_1,
*************** copy_cfg_body (inline_data * id, gcov_ty
*** 990,996 ****
    FOR_ALL_BB_FN (bb, cfun_to_copy)
      bb->aux = NULL;
  
!   if (saving_or_cloning)
      pop_cfun ();
  
    return new_fndecl;
--- 964,970 ----
    FOR_ALL_BB_FN (bb, cfun_to_copy)
      bb->aux = NULL;
  
!   if (versioning_or_cloning)
      pop_cfun ();
  
    return new_fndecl;
*************** initialize_inlined_parameters (inline_da
*** 1158,1165 ****
  
    /* Figure out what the parameters are.  */
    parms = DECL_ARGUMENTS (fn);
-   if (fn == current_function_decl)
-     parms = cfun->saved_args;
  
    /* Loop through the parameter declarations, replacing each with an
       equivalent VAR_DECL, appropriately initialized.  */
--- 1132,1137 ----
*************** initialize_inlined_parameters (inline_da
*** 1179,1186 ****
  
    /* Initialize the static chain.  */
    p = DECL_STRUCT_FUNCTION (fn)->static_chain_decl;
!   if (fn == current_function_decl)
!     p = DECL_STRUCT_FUNCTION (fn)->saved_static_chain_decl;
    if (p)
      {
        /* No static chain?  Seems like a bug in tree-nested.c.  */
--- 1151,1157 ----
  
    /* Initialize the static chain.  */
    p = DECL_STRUCT_FUNCTION (fn)->static_chain_decl;
!   gcc_assert (fn != current_function_decl);
    if (p)
      {
        /* No static chain?  Seems like a bug in tree-nested.c.  */
*************** expand_call_inline (basic_block bb, tree
*** 2003,2008 ****
--- 1974,1980 ----
  	}
        goto egress;
      }
+   fn = cg_edge->callee->decl;
  
  #ifdef ENABLE_CHECKING
    if (cg_edge->callee->decl != id->node->decl)
*************** expand_call_inline (basic_block bb, tree
*** 2059,2067 ****
    /* Record the function we are about to inline.  */
    id->callee = fn;
  
!   if (DECL_STRUCT_FUNCTION (fn)->saved_blocks)
!     add_lexical_block (id->block, remap_blocks (DECL_STRUCT_FUNCTION (fn)->saved_blocks, id));
!   else if (DECL_INITIAL (fn))
      add_lexical_block (id->block, remap_blocks (DECL_INITIAL (fn), id));
  
    /* Return statements in the function body will be replaced by jumps
--- 2031,2037 ----
    /* Record the function we are about to inline.  */
    id->callee = fn;
  
!   if (DECL_INITIAL (fn))
      add_lexical_block (id->block, remap_blocks (DECL_INITIAL (fn), id));
  
    /* Return statements in the function body will be replaced by jumps
*************** expand_call_inline (basic_block bb, tree
*** 2119,2126 ****
  
    /* Add local vars in this inlined callee to caller.  */
    t_step = id->callee_cfun->unexpanded_var_list;
-   if (id->callee_cfun->saved_unexpanded_var_list)
-     t_step = id->callee_cfun->saved_unexpanded_var_list;
    for (; t_step; t_step = TREE_CHAIN (t_step))
      {
        var = TREE_VALUE (t_step);
--- 2089,2094 ----
*************** clone_body (tree clone, tree fn, void *a
*** 2295,2380 ****
    append_to_statement_list_force (copy_generic_body (&id), &DECL_SAVED_TREE (clone));
  }
  
- /* Save duplicate body in FN.  MAP is used to pass around splay tree
-    used to update arguments in restore_body.  */
- 
- /* Make and return duplicate of body in FN.  Put copies of DECL_ARGUMENTS
-    in *arg_copy and of the static chain, if any, in *sc_copy.  */
- 
- void
- save_body (tree fn, tree *arg_copy, tree *sc_copy)
- {
-   inline_data id;
-   tree newdecl, *parg;
-   basic_block fn_entry_block;
-   tree t_step;
- 
-   memset (&id, 0, sizeof (id));
-   id.callee = fn;
-   id.callee_cfun = DECL_STRUCT_FUNCTION (fn);
-   id.caller = fn;
-   id.node = cgraph_node (fn);
-   id.saving_p = true;
-   id.decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
-   *arg_copy = DECL_ARGUMENTS (fn);
- 
-   for (parg = arg_copy; *parg; parg = &TREE_CHAIN (*parg))
-     {
-       tree new = copy_node (*parg);
- 
-       lang_hooks.dup_lang_specific_decl (new);
-       DECL_ABSTRACT_ORIGIN (new) = DECL_ORIGIN (*parg);
-       insert_decl_map (&id, *parg, new);
-       TREE_CHAIN (new) = TREE_CHAIN (*parg);
-       *parg = new;
-     }
- 
-   *sc_copy = DECL_STRUCT_FUNCTION (fn)->static_chain_decl;
-   if (*sc_copy)
-     {
-       tree new = copy_node (*sc_copy);
- 
-       lang_hooks.dup_lang_specific_decl (new);
-       DECL_ABSTRACT_ORIGIN (new) = DECL_ORIGIN (*sc_copy);
-       insert_decl_map (&id, *sc_copy, new);
-       TREE_CHAIN (new) = TREE_CHAIN (*sc_copy);
-       *sc_copy = new;
-     }
- 
-   /* We're not inside any EH region.  */
-   id.eh_region = -1;
- 
-   insert_decl_map (&id, DECL_RESULT (fn), DECL_RESULT (fn));
- 
-   DECL_STRUCT_FUNCTION (fn)->saved_blocks
-     = remap_blocks (DECL_INITIAL (fn), &id);
-   for (t_step = id.callee_cfun->unexpanded_var_list;
-        t_step;
-        t_step = TREE_CHAIN (t_step))
-     {
-       tree var = TREE_VALUE (t_step);
-       if (TREE_STATIC (var) && !TREE_ASM_WRITTEN (var))
- 	cfun->saved_unexpanded_var_list
- 	  = tree_cons (NULL_TREE, var, cfun->saved_unexpanded_var_list);
-       else 
- 	cfun->saved_unexpanded_var_list
- 	  = tree_cons (NULL_TREE, remap_decl (var, &id),
- 		       cfun->saved_unexpanded_var_list);
-     }
- 
-   /* Actually copy the body, including a new (struct function *) and CFG.
-      EH info is also duplicated so its labels point into the copied
-      CFG, not the original.  */
-   fn_entry_block = ENTRY_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (fn));
-   newdecl = copy_body (&id, fn_entry_block->count, fn_entry_block->frequency,
- 		       NULL, NULL);
-   DECL_STRUCT_FUNCTION (fn)->saved_cfg = DECL_STRUCT_FUNCTION (newdecl)->cfg;
-   DECL_STRUCT_FUNCTION (fn)->saved_eh = DECL_STRUCT_FUNCTION (newdecl)->eh;
- 
-   /* Clean up.  */
-   splay_tree_delete (id.decl_map);
- }
- 
  /* Passed to walk_tree.  Copies the node pointed to, if appropriate.  */
  
  tree
--- 2263,2268 ----
*************** tree_versionable_function_p (tree fndecl
*** 2773,2779 ****
     body, TREE_MAP represents the mapping between these 
     trees.  */
  void
! tree_function_versioning (tree old_decl, tree new_decl, varray_type tree_map)
  {
    struct cgraph_node *old_version_node;
    struct cgraph_node *new_version_node;
--- 2661,2667 ----
     body, TREE_MAP represents the mapping between these 
     trees.  */
  void
! tree_function_versioning (tree old_decl, tree new_decl, varray_type tree_map, bool update_clones)
  {
    struct cgraph_node *old_version_node;
    struct cgraph_node *new_version_node;
*************** tree_function_versioning (tree old_decl,
*** 2799,2806 ****
    DECL_ABSTRACT_ORIGIN (new_decl) = DECL_ORIGIN (old_decl);
  
    /* Generate a new name for the new version. */
!   DECL_NAME (new_decl) =
!     create_tmp_var_name (NULL);
    /* Create a new SYMBOL_REF rtx for the new name. */
    if (DECL_RTL (old_decl) != NULL)
      {
--- 2687,2695 ----
    DECL_ABSTRACT_ORIGIN (new_decl) = DECL_ORIGIN (old_decl);
  
    /* Generate a new name for the new version. */
!   if (!update_clones)
!     DECL_NAME (new_decl) =
!       create_tmp_var_name (NULL);
    /* Create a new SYMBOL_REF rtx for the new name. */
    if (DECL_RTL (old_decl) != NULL)
      {
*************** tree_function_versioning (tree old_decl,
*** 2820,2825 ****
--- 2709,2715 ----
    id.current_node = cgraph_node (old_decl);
    
    id.versioning_p = true;
+   id.update_clones_p = update_clones;
    id.decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
    id.caller = new_decl;
    id.callee = old_decl;
*************** replace_ref_tree (inline_data * id, tree
*** 2946,2950 ****
  static inline bool
  inlining_p (inline_data * id)
  {
!   return (!id->saving_p && !id->cloning_p && !id->versioning_p);
  }
--- 2836,2840 ----
  static inline bool
  inlining_p (inline_data * id)
  {
!   return (!id->cloning_p && !id->versioning_p);
  }
Index: tree-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.h,v
retrieving revision 1.19
diff -c -3 -p -r1.19 tree-inline.h
*** tree-inline.h	1 Aug 2005 07:47:25 -0000	1.19
--- tree-inline.h	12 Aug 2005 23:06:10 -0000
*************** void push_cfun (struct function *new_cfu
*** 35,41 ****
  void pop_cfun (void);
  int estimate_num_insns (tree expr);
  bool tree_versionable_function_p (tree);
! void tree_function_versioning (tree, tree, varray_type);
  
  /* Copy a declaration when one function is substituted inline into
     another.  It is used also for versioning.  */
--- 35,41 ----
  void pop_cfun (void);
  int estimate_num_insns (tree expr);
  bool tree_versionable_function_p (tree);
! void tree_function_versioning (tree, tree, varray_type, bool);
  
  /* Copy a declaration when one function is substituted inline into
     another.  It is used also for versioning.  */
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 2.121
diff -c -3 -p -r2.121 tree-optimize.c
*** tree-optimize.c	28 Jul 2005 21:45:27 -0000	2.121
--- tree-optimize.c	12 Aug 2005 23:06:10 -0000
*************** void
*** 342,353 ****
  tree_rest_of_compilation (tree fndecl)
  {
    location_t saved_loc;
!   struct cgraph_node *saved_node = NULL, *node;
  
    timevar_push (TV_EXPAND);
  
    gcc_assert (!flag_unit_at_a_time || cgraph_global_info_ready);
  
    /* Initialize the RTL code for the function.  */
    current_function_decl = fndecl;
    saved_loc = input_location;
--- 342,361 ----
  tree_rest_of_compilation (tree fndecl)
  {
    location_t saved_loc;
!   struct cgraph_node *node;
  
    timevar_push (TV_EXPAND);
  
    gcc_assert (!flag_unit_at_a_time || cgraph_global_info_ready);
  
+   node = cgraph_node (fndecl);
+ 
+   /* We might need the body of this function so that we can expand
+      it inline somewhere else.  This means not lowering some constructs
+      such as exception handling.  */
+   if (cgraph_preserve_function_body_p (fndecl))
+     save_inline_function_body (node);
+ 
    /* Initialize the RTL code for the function.  */
    current_function_decl = fndecl;
    saved_loc = input_location;
*************** tree_rest_of_compilation (tree fndecl)
*** 361,386 ****
    cfun->x_dont_save_pending_sizes_p = 1;
    cfun->after_inlining = true;
  
-   node = cgraph_node (fndecl);
- 
-   /* We might need the body of this function so that we can expand
-      it inline somewhere else.  This means not lowering some constructs
-      such as exception handling.  */
-   if (cgraph_preserve_function_body_p (fndecl))
-     {
-       if (!flag_unit_at_a_time)
- 	{
- 	  struct cgraph_edge *e;
- 
- 	  saved_node = cgraph_clone_node (node, node->count, 1, false);
- 	  for (e = saved_node->callees; e; e = e->next_callee)
- 	    if (!e->inline_failed)
- 	      cgraph_clone_inlined_nodes (e, true);
- 	}
-       cfun->saved_static_chain_decl = cfun->static_chain_decl;
-       save_body (fndecl, &cfun->saved_args, &cfun->saved_static_chain_decl);
-     }
- 
    if (flag_inline_trees)
      {
        struct cgraph_edge *e;
--- 369,374 ----
*************** tree_rest_of_compilation (tree fndecl)
*** 423,462 ****
    /* Release the default bitmap obstack.  */
    bitmap_obstack_release (NULL);
    
!   /* Restore original body if still needed.  */
!   if (cfun->saved_cfg)
!     {
!       DECL_ARGUMENTS (fndecl) = cfun->saved_args;
!       cfun->cfg = cfun->saved_cfg;
!       cfun->eh = cfun->saved_eh;
!       DECL_INITIAL (fndecl) = cfun->saved_blocks;
!       cfun->unexpanded_var_list = cfun->saved_unexpanded_var_list;
!       cfun->saved_cfg = NULL;
!       cfun->saved_eh = NULL;
!       cfun->saved_args = NULL_TREE;
!       cfun->saved_blocks = NULL_TREE;
!       cfun->saved_unexpanded_var_list = NULL_TREE;
!       cfun->static_chain_decl = cfun->saved_static_chain_decl;
!       cfun->saved_static_chain_decl = NULL;
!       /* When not in unit-at-a-time mode, we must preserve out of line copy
! 	 representing node before inlining.  Restore original outgoing edges
! 	 using clone we created earlier.  */
!       if (!flag_unit_at_a_time)
! 	{
! 	  struct cgraph_edge *e;
! 
! 	  node = cgraph_node (current_function_decl);
! 	  cgraph_node_remove_callees (node);
! 	  node->callees = saved_node->callees;
! 	  saved_node->callees = NULL;
! 	  update_inlined_to_pointers (node, node);
! 	  for (e = node->callees; e; e = e->next_callee)
! 	    e->caller = node;
! 	  cgraph_remove_node (saved_node);
! 	}
!     }
!   else
!     DECL_SAVED_TREE (fndecl) = NULL;
    cfun = 0;
  
    /* If requested, warn about function definitions where the function will
--- 411,417 ----
    /* Release the default bitmap obstack.  */
    bitmap_obstack_release (NULL);
    
!   DECL_SAVED_TREE (fndecl) = NULL;
    cfun = 0;
  
    /* If requested, warn about function definitions where the function will
Index: java/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/decl.c,v
retrieving revision 1.227
diff -c -3 -p -r1.227 decl.c
*** java/decl.c	2 Jul 2005 10:55:06 -0000	1.227
--- java/decl.c	12 Aug 2005 23:06:12 -0000
*************** end_java_method (void)
*** 2057,2063 ****
  		     attach_init_test_initialization_flags, block_body);
      }
  
-   flag_unit_at_a_time = 0;
    finish_method (fndecl);
  
    if (! flag_unit_at_a_time)
--- 2057,2062 ----


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