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]

[gomp] cleanup tree-inline.c, part 1


I hadn't realized what horrible non-modular things had been accreting
in tree-inline.c over the last couple of years.  This is the beginning
of a rearrangement to allow this to be used for omp parallel lowering.


r~


        * tree-inline.c (struct copy_body_data): Rename from inline_data.
        Rename callee->src, caller->dst.  Remove ipa_info.  Replace
        cloning_p, saving_p, versioning_p with transform_parm_to_var,
        transform_call_graph_edges, transform_new_cfg,
        transform_return_to_modify, transform_lang_insert_block.  Update
        all users.
        (replace_ref_tree, inlining_p): Remove.

Index: tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.192.4.6
diff -u -p -r1.192.4.6 tree-inline.c
--- tree-inline.c	20 Sep 2005 21:19:24 -0000	1.192.4.6
+++ tree-inline.c	2 Oct 2005 16:06:15 -0000
@@ -55,7 +55,7 @@ Boston, MA 02110-1301, USA.  */
    non-gimple trees.  */
 #include "tree-gimple.h"
 
-/* Inlining, Saving, Cloning
+/* Inlining, Saving, Cloning, Versioning, Parallelization
 
    Inlining: a function body is duplicated, but the PARM_DECLs are
    remapped into VAR_DECLs, and non-void RETURN_EXPRs become
@@ -74,6 +74,14 @@ Boston, MA 02110-1301, USA.  */
    Duplicate the body, using the given splay tree; some parameters
    will become constants (like 0 or 1).
 
+   Versioning: a function body is duplicated and the result is a new
+   function rather than into blocks of an existing function as with
+   inlining.  Some parameters will become constants.
+
+   Parallelization: a region of a function is duplicated resulting in
+   a new function.  Variables may be replaced with complex expressions
+   to enable shared variable semantics.
+
    All of these will simultaneously lookup any callgraph edges.  If
    we're going to inline the duplicated function body, and the given
    function has some cloned callgraph nodes (one for each place this
@@ -103,72 +111,92 @@ int flag_inline_trees = 0;
    o Provide heuristics to clamp inlining of recursive template
      calls?  */
 
-/* Data required for function inlining.  */
+/* Data required for function body duplication.  */
 
-typedef struct inline_data
+typedef struct copy_body_data
 {
-  /* FUNCTION_DECL for function being inlined.  */
-  tree callee;
-  /* FUNCTION_DECL for function being inlined into.  */
-  tree caller;
+  /* FUNCTION_DECL for function being inlined, or in general the
+     source function providing the original trees.  */
+  tree src_fn;
+  /* FUNCTION_DECL for function being inlined into, or in general
+     the destination function receiving the new trees.  */
+  tree dst_fn;
+  /* Callgraph node of the source function.  */
+  struct cgraph_node *src_node;
+  /* Callgraph node of the destination function.  */
+  struct cgraph_node *dst_node;
   /* 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;
+  struct function *src_cfun;
+
   /* The VAR_DECL for the return value.  */
   tree retvar;
   /* The map from local declarations in the inlined function to
      equivalents in the function into which it is being inlined.  */
   splay_tree decl_map;
-  /* We use the same mechanism to build clones that we do to perform
-     inlining.  However, there are a few places where we need to
-     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.  */
-  struct cgraph_node *current_node;
   /* Current BLOCK.  */
   tree block;
-  varray_type ipa_info;
   /* Exception region the inlined call lie in.  */
   int eh_region;
   /* Take region number in the function being copied, add this value and
      get eh region number of the duplicate in the function we inline into.  */
   int eh_region_offset;
-} inline_data;
+
+  /* We use the same mechanism do all sorts of different things.  Rather
+     than enumerating the different cases, we categorize the behaviour
+     in the various situations.  */
+
+  /* True if PARM_DECLs should be duplicated as VAR_DECLs, i.e. inlining.  */
+  bool transform_parm_to_var;
+
+  /* Indicate the desired behaviour wrt call graph edges.  We can either
+     duplicate the edge (inlining, cloning), move the edge (versioning,
+     parallelization), or move the edges of the clones (saving).  */
+  enum copy_body_cge_which {
+    CB_CGE_DUPLICATE,
+    CB_CGE_MOVE,
+    CB_CGE_MOVE_CLONES
+  } transform_call_graph_edges;
+
+  /* True if a new CFG should be created.  False for inlining, true for
+     everything else.  */
+  bool transform_new_cfg;
+
+  /* True if RETURN_EXPRs should be transformed to just the contained
+     MODIFY_EXPR.  The branch semantics of the return will be handled
+     by manipulating the CFG rather than a statement.  */
+  bool transform_return_to_modify;
+
+  /* True if lang_hooks.decls.insert_block should be invoked when
+     duplicating BLOCK nodes.  */
+  bool transform_lang_insert_block;
+} copy_body_data;
 
 /* Prototypes.  */
 
-static tree declare_return_variable (inline_data *, tree, tree, tree *);
+static tree declare_return_variable (copy_body_data *, tree, tree, tree *);
 static tree copy_body_r (tree *, int *, void *);
-static tree copy_generic_body (inline_data *);
+static tree copy_generic_body (copy_body_data *);
 static bool inlinable_function_p (tree);
-static tree remap_decl (tree, inline_data *);
-static tree remap_type (tree, inline_data *);
-static void remap_block (tree *, inline_data *);
-static tree remap_decl (tree, inline_data *);
-static tree remap_decls (tree, inline_data *);
-static void copy_bind_expr (tree *, int *, inline_data *);
+static tree remap_decl (tree, copy_body_data *);
+static tree remap_type (tree, copy_body_data *);
+static void remap_block (tree *, copy_body_data *);
+static tree remap_decl (tree, copy_body_data *);
+static tree remap_decls (tree, copy_body_data *);
+static void copy_bind_expr (tree *, int *, copy_body_data *);
 static tree mark_local_for_remap_r (tree *, int *, void *);
 static void unsave_expr_1 (tree);
 static tree unsave_r (tree *, int *, void *);
 static void declare_inline_vars (tree, tree);
 static void remap_save_expr (tree *, void *, int *);
-static bool replace_ref_tree (inline_data *, tree *);
-static inline bool inlining_p (inline_data *);
 static void add_lexical_block (tree current_block, tree new_block);
 
 /* Insert a tree->tree mapping for ID.  Despite the name suggests
    that the trees should be variables, it is used for more than that.  */
 
 static void
-insert_decl_map (inline_data *id, tree key, tree value)
+insert_decl_map (copy_body_data *id, tree key, tree value)
 {
   splay_tree_insert (id->decl_map, (splay_tree_key) key,
 		     (splay_tree_value) value);
@@ -183,13 +211,13 @@ insert_decl_map (inline_data *id, tree k
 /* Remap DECL during the copying of the BLOCK tree for the function.  */
 
 static tree
-remap_decl (tree decl, inline_data *id)
+remap_decl (tree decl, copy_body_data *id)
 {
   splay_tree_node n;
   tree fn;
 
   /* We only remap local variables in the current function.  */
-  fn = id->callee;
+  fn = id->src_fn;
 
   /* See if we have remapped this declaration.  */
 
@@ -201,7 +229,7 @@ remap_decl (tree decl, inline_data *id)
     {
       /* Make a copy of the variable or label.  */
       tree t;
-      t = copy_decl_for_dup (decl, fn, id->caller, id->versioning_p);
+      t = copy_decl_for_dup (decl, fn, id->dst_fn, id->transform_parm_to_var);
      
       /* Remember it, so that if we encounter this local entity again
 	 we can reuse this copy.  Do this early because remap_type may
@@ -257,7 +285,7 @@ remap_decl (tree decl, inline_data *id)
 }
 
 static tree
-remap_type (tree type, inline_data *id)
+remap_type (tree type, copy_body_data *id)
 {
   splay_tree_node node;
   tree new, t;
@@ -271,7 +299,7 @@ remap_type (tree type, inline_data *id)
     return (tree) node->value;
 
   /* The type only needs remapping if it's variably modified.  */
-  if (! variably_modified_type_p (type, id->callee))
+  if (! variably_modified_type_p (type, id->src_fn))
     {
       insert_decl_map (id, type, type);
       return type;
@@ -369,7 +397,7 @@ remap_type (tree type, inline_data *id)
 }
 
 static tree
-remap_decls (tree decls, inline_data *id)
+remap_decls (tree decls, copy_body_data *id)
 {
   tree old_var;
   tree new_decls = NULL_TREE;
@@ -382,7 +410,7 @@ remap_decls (tree decls, inline_data *id
       /* We can not chain the local static declarations into the unexpanded_var_list
          as we can't duplicate them or break one decl rule.  Go ahead and link
          them into unexpanded_var_list.  */
-      if (!lang_hooks.tree_inlining.auto_var_in_fn_p (old_var, id->callee)
+      if (!lang_hooks.tree_inlining.auto_var_in_fn_p (old_var, id->src_fn)
 	  && !DECL_EXTERNAL (old_var))
 	{
 	  cfun->unexpanded_var_list = tree_cons (NULL_TREE, old_var,
@@ -413,7 +441,7 @@ remap_decls (tree decls, inline_data *id
    therein.  And hook the new block into the block-tree.  */
 
 static void
-remap_block (tree *block, inline_data *id)
+remap_block (tree *block, copy_body_data *id)
 {
   tree old_block;
   tree new_block;
@@ -430,19 +458,18 @@ remap_block (tree *block, inline_data *i
   /* Remap its variables.  */
   BLOCK_VARS (new_block) = remap_decls (BLOCK_VARS (old_block), id);
 
-  fn = id->caller;
-  if (id->cloning_p)
-    /* We're building a clone; DECL_INITIAL is still
-       error_mark_node, and current_binding_level is the parm
-       binding level.  */
+  fn = id->dst_fn;
+
+  if (id->transform_lang_insert_block)
     lang_hooks.decls.insert_block (new_block);
+
   /* Remember the remapped block.  */
   insert_decl_map (id, old_block, new_block);
 }
 
 /* Copy the whole block tree and root it in id->block.  */
 static tree
-remap_blocks (tree block, inline_data *id)
+remap_blocks (tree block, copy_body_data *id)
 {
   tree t;
   tree new = block;
@@ -473,7 +500,7 @@ copy_statement_list (tree *tp)
 }
 
 static void
-copy_bind_expr (tree *tp, int *walk_subtrees, inline_data *id)
+copy_bind_expr (tree *tp, int *walk_subtrees, copy_body_data *id)
 {
   tree block = BIND_EXPR_BLOCK (*tp);
   /* Copy (and replace) the statement.  */
@@ -491,13 +518,13 @@ copy_bind_expr (tree *tp, int *walk_subt
 }
 
 /* Called from copy_body_id via walk_tree.  DATA is really an
-   `inline_data *'.  */
+   `copy_body_data *'.  */
 
 static tree
 copy_body_r (tree *tp, int *walk_subtrees, void *data)
 {
-  inline_data *id = (inline_data *) data;
-  tree fn = id->callee;
+  copy_body_data *id = (copy_body_data *) data;
+  tree fn = id->src_fn;
   tree new_block;
 
   /* Begin by recognizing trees that we'll completely rewrite for the
@@ -506,9 +533,10 @@ copy_body_r (tree *tp, int *walk_subtree
      into an edge).  Further down, we'll handle trees that get
      duplicated and/or tweaked.  */
 
-  /* If this is a RETURN_STMT, change it into an EXPR_STMT and a
-     GOTO_STMT with the RET_LABEL as its target.  */
-  if (TREE_CODE (*tp) == RETURN_EXPR && inlining_p (id))
+  /* When requested, RETURN_EXPRs should be transformed to just the
+     contained MODIFY_EXPR.  The branch semantics of the return will
+     be handled elsewhere by manipulating the CFG rather than a statement.  */
+  if (TREE_CODE (*tp) == RETURN_EXPR && id->transform_return_to_modify)
     {
       tree assignment = TREE_OPERAND (*tp, 0);
 
@@ -526,7 +554,8 @@ copy_body_r (tree *tp, int *walk_subtree
       else /* Else the RETURN_EXPR returns no value.  */
 	{
 	  *tp = NULL;
-	  return (void *)1;
+	  /* Return anything non-null to stop walking.  */
+	  return (tree)1;
 	}
     }
 
@@ -552,7 +581,7 @@ copy_body_r (tree *tp, int *walk_subtree
     remap_save_expr (tp, id->decl_map, walk_subtrees);
   else if (TREE_CODE (*tp) == LABEL_DECL
 	   && (! DECL_CONTEXT (*tp)
-	       || decl_function_context (*tp) == id->callee))
+	       || decl_function_context (*tp) == id->src_fn))
     /* These may need to be remapped for EH handling.  */
     *tp = remap_decl (*tp, id);
   else if (TREE_CODE (*tp) == BIND_EXPR)
@@ -610,8 +639,7 @@ copy_body_r (tree *tp, int *walk_subtree
 		}
 	    }
 	}
-      else if (TREE_CODE (*tp) == INDIRECT_REF
-	       && !id->versioning_p)
+      else if (TREE_CODE (*tp) == INDIRECT_REF)
 	{
 	  /* Get rid of *& from inline substitutions that can happen when a
 	     pointer argument is an ADDR_EXPR.  */
@@ -643,7 +671,7 @@ copy_body_r (tree *tp, int *walk_subtree
 
       /* Here is the "usual case".  Copy this tree node, and then
 	 tweak some special cases.  */
-      copy_tree_r (tp, walk_subtrees, id->versioning_p ? data : NULL);
+      copy_tree_r (tp, walk_subtrees, NULL);
        
       /* If EXPR has block defined, map it to newly constructed block.
          When inlining we want EXPRs without block appear in the block
@@ -697,7 +725,7 @@ copy_body_r (tree *tp, int *walk_subtree
    later  */
 
 static basic_block
-copy_bb (inline_data *id, basic_block bb, int frequency_scale, int count_scale)
+copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, int count_scale)
 {
   block_stmt_iterator bsi, copy_bsi;
   basic_block copy_basic_block;
@@ -729,16 +757,26 @@ copy_bb (inline_data *id, basic_block bb
 	     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;
+	     
+	      switch (id->transform_call_graph_edges)
 		{
-		  struct cgraph_node *node;
-		  struct cgraph_edge *edge;
+		case CB_CGE_DUPLICATE:
+		  edge = cgraph_edge (id->src_node, orig_stmt);
+		  if (edge)
+		    cgraph_clone_edge (edge, id->dst_node, stmt,
+				       REG_BR_PROB_BASE, 1, true);
+		  break;
 
-		  /* 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;
+		case CB_CGE_MOVE:
+		  edge = cgraph_edge (id->src_node, orig_stmt);
+		  if (edge)
+		    edge->call_stmt = stmt;
+		  break;
+
+		case CB_CGE_MOVE_CLONES:
+		  for (node = id->src_node->next_clone;
 		       node;
 		       node = node->next_clone)
 		    {
@@ -746,39 +784,20 @@ copy_bb (inline_data *id, basic_block bb
 		      gcc_assert (edge);
 		      edge->call_stmt = stmt;
 		    }
-		}
-	      else
-		{
-		  struct cgraph_edge *edge;
+		  break;
 
-		  /* 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;
+		default:
+		  gcc_unreachable ();
 		}
 	    }
 	  /* If you think we can abort here, you are wrong.
 	     There is no region 0 in tree land.  */
-	  gcc_assert (lookup_stmt_eh_region_fn (id->callee_cfun, orig_stmt)
+	  gcc_assert (lookup_stmt_eh_region_fn (id->src_cfun, orig_stmt)
 		      != 0);
 
 	  if (tree_could_throw_p (stmt))
 	    {
-	      int region = lookup_stmt_eh_region_fn (id->callee_cfun, orig_stmt);
+	      int region = lookup_stmt_eh_region_fn (id->src_cfun, orig_stmt);
 	      /* Add an entry for the copied tree in the EH hashtable.
 		 When saving or cloning or versioning, use the hashtable in
 		 cfun, and just copy the EH number.  When inlining, use the
@@ -790,7 +809,7 @@ copy_bb (inline_data *id, basic_block bb
 		 and there is a "current region,"
 		 then associate this tree with the current region
 		 and add edges associated with this region.  */
-	      if ((lookup_stmt_eh_region_fn (id->callee_cfun,
+	      if ((lookup_stmt_eh_region_fn (id->src_cfun,
 					     orig_stmt) <= 0
 		   && id->eh_region > 0)
 		  && tree_could_throw_p (stmt))
@@ -882,12 +901,12 @@ remap_decl_1 (tree decl, void *data)
    another function.  Walks FN via CFG, returns new fndecl.  */
 
 static tree
-copy_cfg_body (inline_data * id, gcov_type count, int frequency,
+copy_cfg_body (copy_body_data * id, gcov_type count, int frequency,
 	       basic_block entry_block_map, basic_block exit_block_map)
 {
-  tree callee_fndecl = id->callee;
+  tree callee_fndecl = id->src_fn;
   /* Original cfun for the callee, doesn't change.  */
-  struct function *callee_cfun = DECL_STRUCT_FUNCTION (callee_fndecl);
+  struct function *src_cfun = DECL_STRUCT_FUNCTION (callee_fndecl);
   /* Copy, built by this function.  */
   struct function *new_cfun;
   /* Place to copy from; when a copy of the function was saved off earlier,
@@ -896,19 +915,18 @@ copy_cfg_body (inline_data * id, gcov_ty
     (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)
+  if (ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count)
     count_scale = (REG_BR_PROB_BASE * count
-		   / ENTRY_BLOCK_PTR_FOR_FUNCTION (callee_cfun)->count);
+		   / ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count);
   else
     count_scale = 1;
 
-  if (ENTRY_BLOCK_PTR_FOR_FUNCTION (callee_cfun)->frequency)
+  if (ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->frequency)
     frequency_scale = (REG_BR_PROB_BASE * frequency
 		       /
-		       ENTRY_BLOCK_PTR_FOR_FUNCTION (callee_cfun)->frequency);
+		       ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->frequency);
   else
     frequency_scale = count_scale;
 
@@ -931,14 +949,11 @@ copy_cfg_body (inline_data * id, gcov_ty
       cfun_to_copy->cfg = cfun_to_copy->saved_cfg;
       cfun_to_copy->eh = cfun_to_copy->saved_eh;
     }
-  id->callee_cfun = cfun_to_copy;
+  id->src_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)
+  /* If requested, create new basic_block_info and label_to_block_maps.
+     Otherwise, insert our new blocks and labels into the existing cfg.  */
+  if (id->transform_new_cfg)
     {
       new_cfun =
 	(struct function *) ggc_alloc_cleared (sizeof (struct function));
@@ -951,16 +966,16 @@ copy_cfg_body (inline_data * id, gcov_ty
       init_empty_tree_cfg ();
 
       ENTRY_BLOCK_PTR->count =
-	(ENTRY_BLOCK_PTR_FOR_FUNCTION (callee_cfun)->count * count_scale /
+	(ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count * count_scale /
 	 REG_BR_PROB_BASE);
       ENTRY_BLOCK_PTR->frequency =
-	(ENTRY_BLOCK_PTR_FOR_FUNCTION (callee_cfun)->frequency *
+	(ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->frequency *
 	 frequency_scale / REG_BR_PROB_BASE);
       EXIT_BLOCK_PTR->count =
-	(EXIT_BLOCK_PTR_FOR_FUNCTION (callee_cfun)->count * count_scale /
+	(EXIT_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count * count_scale /
 	 REG_BR_PROB_BASE);
       EXIT_BLOCK_PTR->frequency =
-	(EXIT_BLOCK_PTR_FOR_FUNCTION (callee_cfun)->frequency *
+	(EXIT_BLOCK_PTR_FOR_FUNCTION (src_cfun)->frequency *
 	 frequency_scale / REG_BR_PROB_BASE);
 
       entry_block_map = ENTRY_BLOCK_PTR;
@@ -970,16 +985,13 @@ copy_cfg_body (inline_data * id, gcov_ty
   ENTRY_BLOCK_PTR_FOR_FUNCTION (cfun_to_copy)->aux = entry_block_map;
   EXIT_BLOCK_PTR_FOR_FUNCTION (cfun_to_copy)->aux = exit_block_map;
 
-
   /* Duplicate any exception-handling regions.  */
   if (cfun->eh)
     {
-      if (saving_or_cloning)
+      if (id->transform_new_cfg)
         init_eh_for_function ();
-      id->eh_region_offset = duplicate_eh_regions (cfun_to_copy,
-		     				   remap_decl_1,
-						   id, id->eh_region);
-      gcc_assert (inlining_p (id) || !id->eh_region_offset);
+      id->eh_region_offset
+	= duplicate_eh_regions (cfun_to_copy, remap_decl_1, id, id->eh_region);
     }
   /* Use aux pointers to map the original blocks to copy.  */
   FOR_EACH_BB_FN (bb, cfun_to_copy)
@@ -990,7 +1002,7 @@ copy_cfg_body (inline_data * id, gcov_ty
   FOR_ALL_BB_FN (bb, cfun_to_copy)
     bb->aux = NULL;
 
-  if (saving_or_cloning)
+  if (id->transform_new_cfg)
     pop_cfun ();
 
   return new_fndecl;
@@ -1000,10 +1012,10 @@ copy_cfg_body (inline_data * id, gcov_ty
    another function.  */
 
 static tree
-copy_generic_body (inline_data *id)
+copy_generic_body (copy_body_data *id)
 {
   tree body;
-  tree fndecl = id->callee;
+  tree fndecl = id->src_fn;
 
   body = DECL_SAVED_TREE (fndecl);
   walk_tree (&body, copy_body_r, id, NULL);
@@ -1012,10 +1024,10 @@ copy_generic_body (inline_data *id)
 }
 
 static tree
-copy_body (inline_data *id, gcov_type count, int frequency,
+copy_body (copy_body_data *id, gcov_type count, int frequency,
 	   basic_block entry_block_map, basic_block exit_block_map)
 {
-  tree fndecl = id->callee;
+  tree fndecl = id->src_fn;
   tree body;
 
   /* If this body has a CFG, walk CFG and copy.  */
@@ -1042,7 +1054,7 @@ self_inlining_addr_expr (tree value, tre
 }
 
 static void
-setup_one_parameter (inline_data *id, tree p, tree value, tree fn,
+setup_one_parameter (copy_body_data *id, tree p, tree value, tree fn,
 		     basic_block bb, tree *vars)
 {
   tree init_stmt;
@@ -1077,7 +1089,7 @@ setup_one_parameter (inline_data *id, tr
   /* Make an equivalent VAR_DECL.  Note that we must NOT remap the type
      here since the type of this decl must be visible to the calling
      function.  */
-  var = copy_decl_for_dup (p, fn, id->caller, /*versioning=*/false);
+  var = copy_decl_for_dup (p, fn, id->dst_fn, true);
 
   /* See if the frontend wants to pass this by invisible reference.  If
      so, our new VAR_DECL will have REFERENCE_TYPE, and we need to
@@ -1147,7 +1159,7 @@ setup_one_parameter (inline_data *id, tr
    top of the stack in ID from the ARGS (presented as a TREE_LIST).  */
 
 static void
-initialize_inlined_parameters (inline_data *id, tree args, tree static_chain,
+initialize_inlined_parameters (copy_body_data *id, tree args, tree static_chain,
 			       tree fn, basic_block bb)
 {
   tree parms;
@@ -1206,11 +1218,11 @@ initialize_inlined_parameters (inline_da
    holds the result as seen by the caller.  */
 
 static tree
-declare_return_variable (inline_data *id, tree return_slot_addr,
+declare_return_variable (copy_body_data *id, tree return_slot_addr,
 			 tree modify_dest, tree *use_p)
 {
-  tree callee = id->callee;
-  tree caller = id->caller;
+  tree callee = id->src_fn;
+  tree caller = id->dst_fn;
   tree result = DECL_RESULT (callee);
   tree callee_type = TREE_TYPE (result);
   tree caller_type = TREE_TYPE (TREE_TYPE (callee));
@@ -1275,7 +1287,7 @@ declare_return_variable (inline_data *id
 
   gcc_assert (TREE_CODE (TYPE_SIZE_UNIT (callee_type)) == INTEGER_CST);
 
-  var = copy_decl_for_dup (result, callee, caller, /*versioning=*/false);
+  var = copy_decl_for_dup (result, callee, caller, true);
 
   DECL_SEEN_IN_BIND_EXPR_P (var) = 1;
   DECL_STRUCT_FUNCTION (caller)->unexpanded_var_list
@@ -1900,7 +1912,7 @@ add_lexical_block (tree current_block, t
 static bool
 expand_call_inline (basic_block bb, tree stmt, tree *tp, void *data)
 {
-  inline_data *id;
+  copy_body_data *id;
   tree t;
   tree use_retvar;
   tree fn;
@@ -1921,7 +1933,7 @@ expand_call_inline (basic_block bb, tree
   tree decl;
 
   /* See what we've got.  */
-  id = (inline_data *) data;
+  id = (copy_body_data *) data;
   t = *tp;
 
   /* Set input_location here so we get the right instantiation context
@@ -1957,10 +1969,10 @@ expand_call_inline (basic_block bb, tree
 
   /* Objective C and fortran still calls tree_rest_of_compilation directly.
      Kill this check once this is fixed.  */
-  if (!id->current_node->analyzed)
+  if (!id->src_node->analyzed)
     goto egress;
 
-  cg_edge = cgraph_edge (id->current_node, stmt);
+  cg_edge = cgraph_edge (id->src_node, stmt);
 
   /* Constant propagation on argument done during previous inlining
      may create new direct call.  Produce an edge for it.  */
@@ -1973,7 +1985,7 @@ expand_call_inline (basic_block bb, tree
          constant propagating arguments.  In all other cases we hit a bug
          (incorrect node sharing is most common reason for missing edges.  */
       gcc_assert (dest->needed || !flag_unit_at_a_time);
-      cgraph_create_edge (id->node, dest, stmt,
+      cgraph_create_edge (id->dst_node, dest, stmt,
 			  bb->count, bb->loop_depth)->inline_failed
 	= N_("originally indirect function call not considered for inlining");
       goto egress;
@@ -2005,7 +2017,7 @@ expand_call_inline (basic_block bb, tree
     }
 
 #ifdef ENABLE_CHECKING
-  if (cg_edge->callee->decl != id->node->decl)
+  if (cg_edge->callee->decl != id->dst_node->decl)
     verify_cgraph_node (cg_edge->callee);
 #endif
 
@@ -2057,7 +2069,7 @@ expand_call_inline (basic_block bb, tree
   initialize_inlined_parameters (id, args, TREE_OPERAND (t, 2), fn, bb);
 
   /* Record the function we are about to inline.  */
-  id->callee = fn;
+  id->src_fn = fn;
 
   if (DECL_STRUCT_FUNCTION (fn)->saved_blocks)
     add_lexical_block (id->block, remap_blocks (DECL_STRUCT_FUNCTION (fn)->saved_blocks, id));
@@ -2102,12 +2114,12 @@ expand_call_inline (basic_block bb, tree
 
   /* After we've initialized the parameters, we insert the body of the
      function itself.  */
-  old_node = id->current_node;
+  old_node = id->src_node;
 
-  /* Anoint the callee-to-be-duplicated as the "current_node."  When
+  /* Anoint the callee-to-be-duplicated as the "src_node."  When
      CALL_EXPRs within callee are duplicated, the edges from callee to
      callee's callees (caller's grandchildren) will be cloned.  */
-  id->current_node = cg_edge->callee;
+  id->src_node = cg_edge->callee;
 
   /* This is it.  Duplicate the callee body.  Assume callee is
      pre-gimplified.  Note that we must not alter the caller
@@ -2115,12 +2127,12 @@ expand_call_inline (basic_block bb, tree
      a self-referential call; if we're calling ourselves, we need to
      duplicate our body before altering anything.  */
   copy_body (id, bb->count, bb->frequency, bb, return_block);
-  id->current_node = old_node;
+  id->src_node = old_node;
 
   /* 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;
+  t_step = id->src_cfun->unexpanded_var_list;
+  if (id->src_cfun->saved_unexpanded_var_list)
+    t_step = id->src_cfun->saved_unexpanded_var_list;
   for (; t_step; t_step = TREE_CHAIN (t_step))
     {
       var = TREE_VALUE (t_step);
@@ -2183,7 +2195,7 @@ expand_call_inline (basic_block bb, tree
    to the CALL_EXPR, not the tree itself.  */
 
 static bool
-gimple_expand_calls_inline (basic_block bb, inline_data *id)
+gimple_expand_calls_inline (basic_block bb, copy_body_data *id)
 {
   block_stmt_iterator bsi;
 
@@ -2210,7 +2222,7 @@ gimple_expand_calls_inline (basic_block 
 void
 optimize_inline_calls (tree fn)
 {
-  inline_data id;
+  copy_body_data id;
   tree prev_fn;
   basic_block bb;
   /* There is no point in performing inlining if errors have already
@@ -2222,15 +2234,22 @@ optimize_inline_calls (tree fn)
   /* Clear out ID.  */
   memset (&id, 0, sizeof (id));
 
-  id.current_node = id.node = cgraph_node (fn);
-  id.caller = fn;
+  id.src_node = id.dst_node = cgraph_node (fn);
+  id.dst_fn = fn;
   /* Or any functions that aren't finished yet.  */
   prev_fn = NULL_TREE;
   if (current_function_decl)
     {
-      id.caller = current_function_decl;
+      id.dst_fn = current_function_decl;
       prev_fn = current_function_decl;
     }
+
+  id.transform_parm_to_var = true;
+  id.transform_call_graph_edges = CB_CGE_DUPLICATE;
+  id.transform_new_cfg = false;
+  id.transform_return_to_modify = true;
+  id.transform_lang_insert_block = false;
+
   push_gimplify_context ();
 
   /* Reach the trees by walking over the CFG, and note the
@@ -2242,7 +2261,6 @@ optimize_inline_calls (tree fn)
   FOR_EACH_BB (bb)
     gimple_expand_calls_inline (bb, &id);
 
-
   pop_gimplify_context (NULL);
   /* Renumber the (code) basic_blocks consecutively.  */
   compact_blocks ();
@@ -2253,10 +2271,10 @@ optimize_inline_calls (tree fn)
     {
       struct cgraph_edge *e;
 
-      verify_cgraph_node (id.node);
+      verify_cgraph_node (id.dst_node);
 
       /* Double check that we inlined everything we are supposed to inline.  */
-      for (e = id.node->callees; e; e = e->next_callee)
+      for (e = id.dst_node->callees; e; e = e->next_callee)
 	gcc_assert (e->inline_failed);
     }
 #endif
@@ -2274,19 +2292,21 @@ optimize_inline_calls (tree fn)
 void
 clone_body (tree clone, tree fn, void *arg_map)
 {
-  inline_data id;
+  copy_body_data id;
 
   /* Clone the body, as if we were making an inline call.  But, remap the
      parameters in the callee to the parameters of caller.  */
   memset (&id, 0, sizeof (id));
-  id.caller = clone;
-  id.callee = fn;
-  id.callee_cfun = DECL_STRUCT_FUNCTION (fn);
+  id.src_fn = fn;
+  id.dst_fn = clone;
+  id.src_cfun = DECL_STRUCT_FUNCTION (fn);
   id.decl_map = (splay_tree)arg_map;
 
-  /* Cloning is treated slightly differently from inlining.  Set
-     CLONING_P so that it's clear which operation we're performing.  */
-  id.cloning_p = true;
+  id.transform_parm_to_var = false;
+  id.transform_call_graph_edges = CB_CGE_DUPLICATE;
+  id.transform_new_cfg = true;
+  id.transform_return_to_modify = false;
+  id.transform_lang_insert_block = true;
 
   /* We're not inside any EH region.  */
   id.eh_region = -1;
@@ -2304,20 +2324,26 @@ clone_body (tree clone, tree fn, void *a
 void
 save_body (tree fn, tree *arg_copy, tree *sc_copy)
 {
-  inline_data id;
+  copy_body_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.src_fn = fn;
+  id.src_cfun = DECL_STRUCT_FUNCTION (fn);
+  id.dst_fn = fn;
+  id.src_node = cgraph_node (fn);
+  id.dst_node = id.src_node;
   id.decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
-  *arg_copy = DECL_ARGUMENTS (fn);
 
+  id.transform_parm_to_var = false;
+  id.transform_call_graph_edges = CB_CGE_MOVE_CLONES;
+  id.transform_new_cfg = true;
+  id.transform_return_to_modify = false;
+  id.transform_lang_insert_block = false;
+
+  *arg_copy = DECL_ARGUMENTS (fn);
   for (parg = arg_copy; *parg; parg = &TREE_CHAIN (*parg))
     {
       tree new = copy_node (*parg);
@@ -2348,7 +2374,7 @@ save_body (tree fn, tree *arg_copy, tree
 
   DECL_STRUCT_FUNCTION (fn)->saved_blocks
     = remap_blocks (DECL_INITIAL (fn), &id);
-  for (t_step = id.callee_cfun->unexpanded_var_list;
+  for (t_step = id.src_cfun->unexpanded_var_list;
        t_step;
        t_step = TREE_CHAIN (t_step))
     {
@@ -2381,7 +2407,6 @@ tree
 copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
 {
   enum tree_code code = TREE_CODE (*tp);
-  inline_data *id = (inline_data *) data;
 
   /* We make copies of most nodes.  */
   if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
@@ -2394,11 +2419,6 @@ copy_tree_r (tree *tp, int *walk_subtree
       tree chain = TREE_CHAIN (*tp);
       tree new;
 
-      if (id && id->versioning_p && replace_ref_tree (id, tp))
-	{
-	  *walk_subtrees = 0;
-	  return NULL_TREE;
-	}
       /* Copy the node.  */
       new = copy_node (*tp);
 
@@ -2483,13 +2503,13 @@ remap_save_expr (tree *tp, void *st_, in
 
 /* Called via walk_tree.  If *TP points to a DECL_STMT for a local label,
    copies the declaration and enters it in the splay_tree in DATA (which is
-   really an `inline_data *').  */
+   really an `copy_body_data *').  */
 
 static tree
 mark_local_for_remap_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
 			void *data)
 {
-  inline_data *id = (inline_data *) data;
+  copy_body_data *id = (copy_body_data *) data;
 
   /* Don't walk into types.  */
   if (TYPE_P (*tp))
@@ -2502,7 +2522,7 @@ mark_local_for_remap_r (tree *tp, int *w
       /* Copy the decl and remember the copy.  */
       insert_decl_map (id, decl,
 		       copy_decl_for_dup (decl, DECL_CONTEXT (decl),
-					  DECL_CONTEXT (decl),  /*versioning=*/false));
+					  DECL_CONTEXT (decl),  true));
     }
 
   return NULL_TREE;
@@ -2540,7 +2560,7 @@ unsave_expr_1 (tree expr)
 static tree
 unsave_r (tree *tp, int *walk_subtrees, void *data)
 {
-  inline_data *id = (inline_data *) data;
+  copy_body_data *id = (copy_body_data *) data;
   splay_tree st = id->decl_map;
   splay_tree_node n;
 
@@ -2580,7 +2600,7 @@ unsave_r (tree *tp, int *walk_subtrees, 
 tree
 unsave_expr_now (tree expr)
 {
-  inline_data id;
+  copy_body_data id;
 
   /* There's nothing to do for NULL_TREE.  */
   if (expr == 0)
@@ -2588,10 +2608,16 @@ unsave_expr_now (tree expr)
 
   /* Set up ID.  */
   memset (&id, 0, sizeof (id));
-  id.callee = current_function_decl;
-  id.caller = current_function_decl;
+  id.src_fn = current_function_decl;
+  id.dst_fn = current_function_decl;
   id.decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
 
+  id.transform_parm_to_var = false;
+  id.transform_call_graph_edges = CB_CGE_DUPLICATE;
+  id.transform_new_cfg = false;
+  id.transform_return_to_modify = false;
+  id.transform_lang_insert_block = false;
+
   /* Walk the tree once to find local labels.  */
   walk_tree_without_duplicates (&expr, mark_local_for_remap_r, &id);
 
@@ -2638,17 +2664,17 @@ declare_inline_vars (tree block, tree va
 
 
 /* Copy NODE (which must be a DECL).  The DECL originally was in the FROM_FN,
-   but now it will be in the TO_FN.  VERSIONING means that this function 
-   is used by the versioning utility (not inlining or cloning).  */
+   but now it will be in the TO_FN.  PARM_TO_VAR means enable PARM_DECL to
+   VAR_DECL translation.  */
 
 tree
-copy_decl_for_dup (tree decl, tree from_fn, tree to_fn, bool versioning)
+copy_decl_for_dup (tree decl, tree from_fn, tree to_fn, bool parm_to_var)
 {
   tree copy;
 
   gcc_assert (DECL_P (decl));
   /* Copy the declaration.  */
-  if (!versioning
+  if (parm_to_var
       && (TREE_CODE (decl) == PARM_DECL
 	  || TREE_CODE (decl) == RESULT_DECL))
     {
@@ -2718,7 +2744,7 @@ copy_decl_for_dup (tree decl, tree from_
 
 /* Return a copy of the function's argument tree.  */
 static tree
-copy_arguments_for_versioning (tree orig_parm, inline_data * id)
+copy_arguments_for_versioning (tree orig_parm, copy_body_data * id)
 {
   tree *arg_copy, *parg;
 
@@ -2735,7 +2761,7 @@ copy_arguments_for_versioning (tree orig
 
 /* Return a copy of the function's static chain.  */
 static tree
-copy_static_chain (tree static_chain, inline_data * id)
+copy_static_chain (tree static_chain, copy_body_data * id)
 {
   tree *chain_copy, *pvar;
 
@@ -2777,7 +2803,7 @@ tree_function_versioning (tree old_decl,
 {
   struct cgraph_node *old_version_node;
   struct cgraph_node *new_version_node;
-  inline_data id;
+  copy_body_data id;
   tree p, new_fndecl;
   unsigned i;
   struct ipa_replace_map *replace_info;
@@ -2813,18 +2839,19 @@ tree_function_versioning (tree old_decl,
   /* Prepare the data structures for the tree copy.  */
   memset (&id, 0, sizeof (id));
   
-  /* The new version. */
-  id.node = new_version_node;
-  
-  /* The old version. */
-  id.current_node = cgraph_node (old_decl);
-  
-  id.versioning_p = true;
   id.decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
-  id.caller = new_decl;
-  id.callee = old_decl;
-  id.callee_cfun = DECL_STRUCT_FUNCTION (old_decl);
+  id.src_fn = old_decl;
+  id.dst_fn = new_decl;
+  id.src_node = old_version_node;
+  id.dst_node = new_version_node;
+  id.src_cfun = DECL_STRUCT_FUNCTION (old_decl);
   
+  id.transform_parm_to_var = false;
+  id.transform_call_graph_edges = CB_CGE_MOVE;
+  id.transform_new_cfg = true;
+  id.transform_return_to_modify = false;
+  id.transform_lang_insert_block = false;
+
   current_function_decl = new_decl;
   
   /* Copy the function's static chain.  */
@@ -2843,17 +2870,15 @@ tree_function_versioning (tree old_decl,
     for (i = 0; i < VARRAY_ACTIVE_SIZE (tree_map); i++)
       {
 	replace_info = VARRAY_GENERIC_PTR (tree_map, i);
-	if (replace_info->replace_p && !replace_info->ref_p)
+	if (replace_info->replace_p)
 	  insert_decl_map (&id, replace_info->old_tree,
 			   replace_info->new_tree);
-	else if (replace_info->replace_p && replace_info->ref_p)
-	  id.ipa_info = tree_map;
       }
   
-  DECL_INITIAL (new_decl) = remap_blocks (DECL_INITIAL (id.callee), &id);
+  DECL_INITIAL (new_decl) = remap_blocks (DECL_INITIAL (id.src_fn), &id);
   
   /* Renumber the lexical scoping (non-code) blocks consecutively.  */
-  number_blocks (id.caller);
+  number_blocks (id.dst_fn);
   
   if (DECL_STRUCT_FUNCTION (old_decl)->unexpanded_var_list != NULL_TREE)
     /* Add local vars.  */
@@ -2903,48 +2928,3 @@ tree_function_versioning (tree old_decl,
   fold_cond_expr_cond ();
   return;
 }
-
-/*  Replace an INDIRECT_REF tree of a given DECL tree with a new 
-    given tree.
-    ID->ipa_info keeps the old tree and the new tree.  
-    TP points to the INDIRECT REF tree.  Return true if 
-    the trees were replaced.  */
-static bool
-replace_ref_tree (inline_data * id, tree * tp)
-{
-  bool replaced = false;
-  tree new;
-
-  if (id->ipa_info && VARRAY_ACTIVE_SIZE (id->ipa_info) > 0)
-    {
-      unsigned i;
-
-      for (i = 0; i < VARRAY_ACTIVE_SIZE (id->ipa_info); i++)
-	{
-	  struct ipa_replace_map *replace_info;
-	  replace_info = VARRAY_GENERIC_PTR (id->ipa_info, i);
-
-	  if (replace_info->replace_p && replace_info->ref_p)
-	    {
-	      tree old_tree = replace_info->old_tree;
-	      tree new_tree = replace_info->new_tree;
-
-	      if (TREE_CODE (*tp) == INDIRECT_REF
-		  && TREE_OPERAND (*tp, 0) == old_tree)
-		{
-		  new = copy_node (new_tree);
-		  *tp = new;
-		  replaced = true;
-		}
-	    }
-	}
-    }
-  return replaced;
-}
-
-/* Return true if we are inlining.  */
-static inline bool
-inlining_p (inline_data * id)
-{
-  return (!id->saving_p && !id->cloning_p && !id->versioning_p);
-}


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