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]

Re: [PATCH] Kill function body saving code


> >
> >Bootstrapped/regtested i686-pc-gnu-linux, ppc-linux in progress, OK?
> 
> Awesome, I was wondering if you were going to do this :)
> 
> Next time you put a patch up, for ease of reading can you please diff  
> without
> whitespace changes? There are a number of lines in the patch that have
> zero changes, but are in the diff :)

Well, looking into diff, I found only one such accidental whitespace
change, but here is fixed patch.  I also fixed one occurence of line
longer than 80 characters.

	* 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.
Index: cgraph.c
===================================================================
*** cgraph.c	(revision 107562)
--- cgraph.c	(working copy)
*************** 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
===================================================================
*** cgraph.h	(revision 107562)
--- cgraph.h	(working copy)
*************** 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)
*** 281,286 ****
--- 287,293 ----
  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
===================================================================
*** cgraphunit.c	(revision 107562)
--- cgraphunit.c	(working copy)
*************** verify_cgraph_node (struct cgraph_node *
*** 748,754 ****
  			    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);
--- 748,755 ----
  			    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
*** 1202,1210 ****
  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.  */
--- 1203,1208 ----
*************** cgraph_function_versioning (struct cgrap
*** 1504,1510 ****
  				     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);
  
--- 1502,1508 ----
  				     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
*** 1521,1523 ****
--- 1519,1575 ----
    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));
+ 
+   cgraph_lower_function (node);
+ 
+   /* 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;
+       first_clone->reachable = 1;
+       /* Recursively clone all bodies.  */
+       for (e = first_clone->callees; e; e = e->next_callee)
+ 	if (!e->inline_failed)
+ 	  cgraph_clone_inlined_nodes (e, true, false);
+     }
+   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: ipa-inline.c
===================================================================
*** ipa-inline.c	(revision 107562)
--- ipa-inline.c	(working copy)
*************** cgraph_mark_inline_edge (struct cgraph_e
*** 156,161 ****
--- 156,164 ----
    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
*** 281,301 ****
  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)
  	{
--- 284,308 ----
  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
*** 1044,1050 ****
          && !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)
  	  {
--- 1051,1057 ----
          && !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)
  	  {
*************** cgraph_decide_inlining_incrementally (st
*** 1067,1073 ****
  	      || (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))
  	    {
--- 1074,1080 ----
  	      || (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: function.h
===================================================================
*** function.h	(revision 107562)
--- function.h	(working copy)
*************** struct expr_status GTY(())
*** 162,185 ****
  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.  */
  
--- 162,174 ----
Index: tree-inline.c
===================================================================
*** tree-inline.c	(revision 107562)
--- tree-inline.c	(working copy)
*************** 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
*** 749,794 ****
  	     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.
--- 746,778 ----
  	     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
*** 916,922 ****
      (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)
--- 900,906 ----
      (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
*** 941,964 ****
  
    *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));
--- 925,938 ----
  
    *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
*** 994,1000 ****
    /* 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,
--- 968,974 ----
    /* 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
*** 1010,1016 ****
    FOR_ALL_BB_FN (bb, cfun_to_copy)
      bb->aux = NULL;
  
!   if (saving_or_cloning)
      pop_cfun ();
  
    return new_fndecl;
--- 984,990 ----
    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
*** 1182,1189 ****
  
    /* 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.  */
--- 1156,1161 ----
*************** initialize_inlined_parameters (inline_da
*** 1203,1210 ****
  
    /* 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.  */
--- 1175,1181 ----
  
    /* 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
*** 2038,2043 ****
--- 2009,2015 ----
  	}
        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
*** 2094,2102 ****
    /* 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
--- 2066,2072 ----
    /* 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
*** 2154,2161 ****
  
    /* 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);
--- 2124,2129 ----
*************** clone_body (tree clone, tree fn, void *a
*** 2330,2415 ****
    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
--- 2298,2303 ----
*************** tree_versionable_function_p (tree fndecl
*** 2808,2814 ****
     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;
--- 2696,2703 ----
     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,
*** 2834,2841 ****
    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)
      {
--- 2723,2731 ----
    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,
*** 2855,2860 ****
--- 2745,2751 ----
    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
*** 2981,2987 ****
  static inline bool
  inlining_p (inline_data * id)
  {
!   return (!id->saving_p && !id->cloning_p && !id->versioning_p);
  }
  
  /* Duplicate a type, fields and all.  */
--- 2872,2878 ----
  static inline bool
  inlining_p (inline_data * id)
  {
!   return (!id->cloning_p && !id->versioning_p);
  }
  
  /* Duplicate a type, fields and all.  */
Index: tree-inline.h
===================================================================
*** tree-inline.h	(revision 107562)
--- tree-inline.h	(working copy)
*************** 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
===================================================================
*** tree-optimize.c	(revision 107562)
--- tree-optimize.c	(working copy)
*************** 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, false);
- 	}
-       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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]