OSDN Git Service

Fix address cost for plus reg const_int.
[pf3gnuchains/gcc-fork.git] / gcc / ipa-cp.c
index 8f1c161..fe335c4 100644 (file)
@@ -1,5 +1,5 @@
 /* Interprocedural constant propagation
-   Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
    Contributed by Razya Ladelsky <RAZYA@il.ibm.com>
    
 This file is part of GCC.
@@ -171,9 +171,8 @@ ipcp_init_cloned_node (struct cgraph_node *orig_node,
                       struct cgraph_node *new_node)
 {
   ipa_check_create_node_params ();
+  ipa_initialize_node_params (new_node);
   IPA_NODE_REF (new_node)->ipcp_orig_node = orig_node;
-  ipa_count_formal_params (new_node);
-  ipa_create_param_decls_array (new_node);
 }
 
 /* Perform intraprocedrual analysis needed for ipcp.  */
@@ -183,39 +182,10 @@ ipcp_analyze_node (struct cgraph_node *node)
   /* Unreachable nodes should have been eliminated before ipcp.  */
   gcc_assert (node->needed || node->reachable);
 
-  ipa_count_formal_params (node);
-  ipa_create_param_decls_array (node);
+  ipa_initialize_node_params (node);
   ipa_detect_param_modifications (node);
 }
 
-/* Recompute all local information since node might've got new
-   direct calls after cloning.  */
-static void
-ipcp_update_cloned_node (struct cgraph_node *new_node)
-{
-  /* We might've introduced new direct calls.  */
-  push_cfun (DECL_STRUCT_FUNCTION (new_node->decl));
-  current_function_decl = new_node->decl;
-  rebuild_cgraph_edges ();
-
-  /* Indirect inlinng rely on fact that we've already analyzed
-     the body..  */
-  if (flag_indirect_inlining)
-    {
-      struct cgraph_edge *cs;
-
-      ipcp_analyze_node (new_node);
-
-      for (cs = new_node->callees; cs; cs = cs->next_callee)
-       {
-         ipa_count_arguments (cs);
-         ipa_compute_jump_functions (cs);
-       }
-    }
-  pop_cfun ();
-  current_function_decl = NULL;
-}
-
 /* Return scale for NODE.  */
 static inline gcov_type
 ipcp_get_node_scale (struct cgraph_node *node)
@@ -300,9 +270,9 @@ ipa_lattice_meet (struct ipcp_lattice *res, struct ipcp_lattice *lat1,
 /* Return the lattice corresponding to the Ith formal parameter of the function
    described by INFO.  */
 static inline struct ipcp_lattice *
-ipcp_get_ith_lattice (struct ipa_node_params *info, int i)
+ipcp_get_lattice (struct ipa_node_params *info, int i)
 {
-  return &(info->ipcp_lattices[i]);
+  return &(info->params[i].ipcp_lattice);
 }
 
 /* Given the jump function JFUNC, compute the lattice LAT that describes the
@@ -312,16 +282,16 @@ static void
 ipcp_lattice_from_jfunc (struct ipa_node_params *info, struct ipcp_lattice *lat,
                         struct ipa_jump_func *jfunc)
 {
-  if (jfunc->type == IPA_CONST)
+  if (jfunc->type == IPA_JF_CONST)
     {
       lat->type = IPA_CONST_VALUE;
       lat->constant = jfunc->value.constant;
     }
-  else if (jfunc->type == IPA_PASS_THROUGH)
+  else if (jfunc->type == IPA_JF_PASS_THROUGH)
     {
       struct ipcp_lattice *caller_lat;
 
-      caller_lat = ipcp_get_ith_lattice (info, jfunc->value.formal_id);
+      caller_lat = ipcp_get_lattice (info, jfunc->value.formal_id);
       lat->type = caller_lat->type;
       lat->constant = caller_lat->constant;
     }
@@ -364,7 +334,7 @@ ipcp_print_all_lattices (FILE * f)
       count = ipa_get_param_count (info);
       for (i = 0; i < count; i++)
        {
-         struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
+         struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
 
          fprintf (f, "    param [%d]: ", i);
          if (lat->type == IPA_CONST_VALUE)
@@ -381,6 +351,45 @@ ipcp_print_all_lattices (FILE * f)
     }
 }
 
+/* Return true if ipcp algorithms would allow cloning NODE.  */
+
+static bool
+ipcp_versionable_function_p (struct cgraph_node *node)
+{
+  tree decl = node->decl;
+  basic_block bb;
+
+  /* There are a number of generic reasons functions cannot be versioned.  */
+  if (!tree_versionable_function_p (decl))
+    return false;
+
+  /* Removing arguments doesn't work if the function takes varargs.  */
+  if (DECL_STRUCT_FUNCTION (decl)->stdarg)
+    return false;
+
+  /* Removing arguments doesn't work if we use __builtin_apply_args.  */
+  FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (decl))
+    {
+      gimple_stmt_iterator gsi;
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+       {
+         const_gimple stmt = gsi_stmt (gsi);
+         tree t;
+
+         if (!is_gimple_call (stmt))
+           continue;
+         t = gimple_call_fndecl (stmt);
+         if (t == NULL_TREE)
+           continue;
+         if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
+             && DECL_FUNCTION_CODE (t) == BUILT_IN_APPLY_ARGS)
+           return false;
+       }
+    }
+
+  return true;
+}
+
 /* Return true if this NODE is viable candidate for cloning.  */
 static bool
 ipcp_cloning_candidate_p (struct cgraph_node *node)
@@ -404,7 +413,7 @@ ipcp_cloning_candidate_p (struct cgraph_node *node)
                 cgraph_node_name (node));
       return false;
     }
-  if (!tree_versionable_function_p (node->decl))
+  if (!ipcp_versionable_function_p (node))
     {
       if (dump_file)
         fprintf (dump_file, "Not considering %s for cloning; body is not versionable.\n",
@@ -426,7 +435,7 @@ ipcp_cloning_candidate_p (struct cgraph_node *node)
                 cgraph_node_name (node));
       return false;
     }
-  if (node->local.inline_summary.self_insns < n_calls)
+  if (node->local.inline_summary.self_size < n_calls)
     {
       if (dump_file)
         fprintf (dump_file, "Considering %s for cloning; code would shrink.\n",
@@ -468,6 +477,7 @@ ipcp_cloning_candidate_p (struct cgraph_node *node)
       if (dump_file)
        fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n",
                 cgraph_node_name (node));
+      return false;
     }
   if (dump_file)
     fprintf (dump_file, "Considering %s for cloning.\n",
@@ -485,9 +495,6 @@ ipcp_initialize_node_lattices (struct cgraph_node *node)
   struct ipa_node_params *info = IPA_NODE_REF (node);
   enum ipa_lattice_type type;
 
-  info->ipcp_lattices = XCNEWVEC (struct ipcp_lattice,
-                                 ipa_get_param_count (info));
-  
   if (ipa_is_called_with_var_arguments (info))
     type = IPA_BOTTOM;
   else if (!node->needed)
@@ -500,7 +507,7 @@ ipcp_initialize_node_lattices (struct cgraph_node *node)
     type = IPA_BOTTOM;
 
   for (i = 0; i < ipa_get_param_count (info) ; i++)
-    ipcp_get_ith_lattice (info, i)->type = type;
+    ipcp_get_lattice (info, i)->type = type;
 }
 
 /* build INTEGER_CST tree with type TREE_TYPE and value according to LAT.
@@ -596,14 +603,14 @@ ipcp_change_tops_to_bottom (void)
       count = ipa_get_param_count (info);
       for (i = 0; i < count; i++)
        {
-         struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
+         struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
          if (lat->type == IPA_TOP)
            {
              prop_again = true;
              if (dump_file)
                {
                  fprintf (dump_file, "Forcing param ");
-                 print_generic_expr (dump_file, ipa_get_ith_param (info, i), 0);
+                 print_generic_expr (dump_file, ipa_get_param (info, i), 0);
                  fprintf (dump_file, " of node %s to bottom.\n",
                           cgraph_node_name (node));
                }
@@ -651,7 +658,7 @@ ipcp_propagate_stage (void)
            {
              jump_func = ipa_get_ith_jump_func (args, i);
              ipcp_lattice_from_jfunc (info, &inc_lat, jump_func);
-             dest_lat = ipcp_get_ith_lattice (callee_info, i);
+             dest_lat = ipcp_get_lattice (callee_info, i);
              ipa_lattice_meet (&new_lat, &inc_lat, dest_lat);
              if (ipcp_lattice_changed (&new_lat, dest_lat))
                {
@@ -709,7 +716,7 @@ ipcp_node_modifiable_p (struct cgraph_node *node)
 {
   /* Once we will be able to do in-place replacement, we can be more
      lax here.  */
-  return tree_versionable_function_p (node->decl);
+  return ipcp_versionable_function_p (node);
 }
 
 /* Print count scale data structures.  */
@@ -761,98 +768,6 @@ ipcp_print_call_profile_counts (FILE * f)
     }
 }
 
-/* Print all counts and probabilities of cfg edges of all functions.  */
-static void
-ipcp_print_edge_profiles (FILE * f)
-{
-  struct cgraph_node *node;
-  basic_block bb;
-  edge_iterator ei;
-  edge e;
-
-  for (node = cgraph_nodes; node; node = node->next)
-    {
-      fprintf (f, "function %s: \n", cgraph_node_name (node));
-      if (node->analyzed)
-       {
-         bb =
-           ENTRY_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (node->decl));
-         fprintf (f, "ENTRY: ");
-         fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
-                  " %d\n", (HOST_WIDE_INT) bb->count, bb->frequency);
-
-         if (bb->succs)
-           FOR_EACH_EDGE (e, ei, bb->succs)
-           {
-             if (e->dest ==
-                 EXIT_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION
-                                              (node->decl)))
-               fprintf (f, "edge ENTRY -> EXIT,  Count");
-             else
-               fprintf (f, "edge ENTRY -> %d,  Count", e->dest->index);
-             fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
-                      " Prob %d\n", (HOST_WIDE_INT) e->count,
-                      e->probability);
-           }
-         FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
-         {
-           fprintf (f, "bb[%d]: ", bb->index);
-           fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
-                    " %d\n", (HOST_WIDE_INT) bb->count, bb->frequency);
-           FOR_EACH_EDGE (e, ei, bb->succs)
-           {
-             if (e->dest ==
-                 EXIT_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION
-                                              (node->decl)))
-               fprintf (f, "edge %d -> EXIT,  Count", e->src->index);
-             else
-               fprintf (f, "edge %d -> %d,  Count", e->src->index,
-                        e->dest->index);
-             fprintf (f, " " HOST_WIDE_INT_PRINT_DEC " Prob %d\n",
-                      (HOST_WIDE_INT) e->count, e->probability);
-           }
-         }
-       }
-    }
-}
-
-/* Print counts and frequencies for all basic blocks of all functions.  */
-static void
-ipcp_print_bb_profiles (FILE * f)
-{
-  basic_block bb;
-  struct cgraph_node *node;
-
-  for (node = cgraph_nodes; node; node = node->next)
-    {
-      fprintf (f, "function %s: \n", cgraph_node_name (node));
-      if (node->analyzed)
-       {
-         bb =
-           ENTRY_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (node->decl));
-         fprintf (f, "ENTRY: Count");
-         fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
-                  " Frequency  %d\n", (HOST_WIDE_INT) bb->count,
-                  bb->frequency);
-
-         FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
-         {
-           fprintf (f, "bb[%d]: Count", bb->index);
-           fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
-                    " Frequency %d\n", (HOST_WIDE_INT) bb->count,
-                    bb->frequency);
-         }
-         bb =
-           EXIT_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (node->decl));
-         fprintf (f, "EXIT: Count");
-         fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
-                  " Frequency %d\n", (HOST_WIDE_INT) bb->count,
-                  bb->frequency);
-
-       }
-    }
-}
-
 /* Print profile info for all functions.  */
 static void
 ipcp_print_profile_data (FILE * f)
@@ -861,10 +776,6 @@ ipcp_print_profile_data (FILE * f)
   ipcp_print_func_profile_counts (f);
   fprintf (f, "\nCS COUNTS stage:\n");
   ipcp_print_call_profile_counts (f);
-  fprintf (f, "\nBB COUNTS and FREQUENCIES :\n");
-  ipcp_print_bb_profiles (f);
-  fprintf (f, "\nCFG EDGES COUNTS and PROBABILITIES :\n");
-  ipcp_print_edge_profiles (f);
 }
 
 /* Build and initialize ipa_replace_map struct according to LAT. This struct is
@@ -877,7 +788,7 @@ ipcp_create_replace_map (tree parm_tree, struct ipcp_lattice *lat)
   struct ipa_replace_map *replace_map;
   tree const_val;
 
-  replace_map = XCNEW (struct ipa_replace_map);
+  replace_map = GGC_NEW (struct ipa_replace_map);
   const_val = build_const_val (lat, TREE_TYPE (parm_tree));
   if (dump_file)
     {
@@ -917,11 +828,11 @@ ipcp_need_redirect_p (struct cgraph_edge *cs)
   count = ipa_get_param_count (orig_callee_info);
   for (i = 0; i < count; i++)
     {
-      struct ipcp_lattice *lat = ipcp_get_ith_lattice (orig_callee_info, i);
+      struct ipcp_lattice *lat = ipcp_get_lattice (orig_callee_info, i);
       if (ipcp_lat_is_const (lat))
        {
          jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
-         if (jump_func->type != IPA_CONST)
+         if (jump_func->type != IPA_JF_CONST)
            return true;
        }
     }
@@ -946,8 +857,8 @@ ipcp_update_callgraph (void)
 
        for (i = 0; i < count; i++)
          {
-           struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
-           tree parm_tree = ipa_get_ith_param (info, i);
+           struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
+           tree parm_tree = ipa_get_param (info, i);
 
            /* We can proactively remove obviously unused arguments.  */
            if (is_gimple_reg (parm_tree)
@@ -964,53 +875,12 @@ ipcp_update_callgraph (void)
        for (cs = node->callers; cs; cs = next)
          {
            next = cs->next_caller;
-           if (ipcp_node_is_clone (cs->caller) || !ipcp_need_redirect_p (cs))
-             {
-               gimple new_stmt;
-               gimple_stmt_iterator gsi;
-
-               current_function_decl = cs->caller->decl;
-               push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl));
-               
-               new_stmt = giple_copy_call_skip_args (cs->call_stmt, args_to_skip);
-               gsi = gsi_for_stmt (cs->call_stmt);
-               gsi_replace (&gsi, new_stmt, true);
-               cgraph_set_call_stmt (cs, new_stmt);
-               pop_cfun ();
-               current_function_decl = NULL;
-             }
-           else
-             {
-               cgraph_redirect_edge_callee (cs, orig_node);
-               gimple_call_set_fndecl (cs->call_stmt, orig_node->decl);
-             }
+           if (!ipcp_node_is_clone (cs->caller) && ipcp_need_redirect_p (cs))
+             cgraph_redirect_edge_callee (cs, orig_node);
          }
       }
 }
 
-/* Update all cfg basic blocks in NODE according to SCALE.  */
-static void
-ipcp_update_bb_counts (struct cgraph_node *node, gcov_type scale)
-{
-  basic_block bb;
-
-  FOR_ALL_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
-    bb->count = bb->count * scale / REG_BR_PROB_BASE;
-}
-
-/* Update all cfg edges in NODE according to SCALE.  */
-static void
-ipcp_update_edges_counts (struct cgraph_node *node, gcov_type scale)
-{
-  basic_block bb;
-  edge_iterator ei;
-  edge e;
-
-  FOR_ALL_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
-    FOR_EACH_EDGE (e, ei, bb->succs)
-    e->count = e->count * scale / REG_BR_PROB_BASE;
-}
-
 /* Update profiling info for versioned functions and the functions they were
    versioned from.  */
 static void
@@ -1034,10 +904,6 @@ ipcp_update_profiling (void)
            cs->count = cs->count * scale / REG_BR_PROB_BASE;
          for (cs = orig_node->callees; cs; cs = cs->next_callee)
            cs->count = cs->count * scale_complement / REG_BR_PROB_BASE;
-         ipcp_update_bb_counts (node, scale);
-         ipcp_update_bb_counts (orig_node, scale_complement);
-         ipcp_update_edges_counts (node, scale);
-         ipcp_update_edges_counts (orig_node, scale_complement);
        }
     }
 }
@@ -1055,7 +921,7 @@ ipcp_estimate_growth (struct cgraph_node *node)
   int growth;
 
   for (cs = node->callers; cs != NULL; cs = cs->next_caller)
-    if (!ipcp_need_redirect_p (cs))
+    if (cs->caller == node || !ipcp_need_redirect_p (cs))
       redirectable_node_callers++;
     else
       need_original = true;
@@ -1063,14 +929,14 @@ ipcp_estimate_growth (struct cgraph_node *node)
   /* If we will be able to fully replace orignal node, we never increase
      program size.  */
   if (!need_original)
-    return false;
+    return 0;
 
   info = IPA_NODE_REF (node);
   count = ipa_get_param_count (info);
   for (i = 0; i < count; i++)
     {
-      struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
-      tree parm_tree = ipa_get_ith_param (info, i);
+      struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
+      tree parm_tree = ipa_get_param (info, i);
 
       /* We can proactively remove obviously unused arguments.  */
       if (is_gimple_reg (parm_tree)
@@ -1086,7 +952,7 @@ ipcp_estimate_growth (struct cgraph_node *node)
      call site.  Precise cost is dificult to get, as our size metric counts
      constants and moves as free.  Generally we are looking for cases that
      small function is called very many times.  */
-  growth = node->local.inline_summary.self_insns
+  growth = node->local.inline_summary.self_size
           - removable_args * redirectable_node_callers;
   if (growth < 0)
     return 0;
@@ -1126,7 +992,7 @@ ipcp_estimate_cloning_cost (struct cgraph_node *node)
     cost /= freq_sum * 1000 / REG_BR_PROB_BASE + 1;
   if (dump_file)
     fprintf (dump_file, "Cost of versioning %s is %i, (size: %i, freq: %i)\n",
-             cgraph_node_name (node), cost, node->local.inline_summary.self_insns,
+             cgraph_node_name (node), cost, node->local.inline_summary.self_size,
             freq_sum);
   return cost + 1;
 }
@@ -1142,8 +1008,8 @@ ipcp_const_param_count (struct cgraph_node *node)
 
   for (i = 0; i < count; i++)
     {
-      struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
-      tree parm_tree = ipa_get_ith_param (info, i);
+      struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
+      tree parm_tree = ipa_get_param (info, i);
       if (ipcp_lat_is_insertable (lat)
          /* Do not count obviously unused arguments.  */
          && (!is_gimple_reg (parm_tree)
@@ -1162,14 +1028,13 @@ ipcp_insert_stage (void)
   struct cgraph_node *node, *node1 = NULL;
   int i;
   VEC (cgraph_edge_p, heap) * redirect_callers;
-  varray_type replace_trees;
-  struct cgraph_edge *cs;
+  VEC (ipa_replace_map_p,gc)* replace_trees;
   int node_callers, count;
   tree parm_tree;
   struct ipa_replace_map *replace_param;
   fibheap_t heap;
-  long overall_insns = 0, new_insns = 0;
-  long max_new_insns;
+  long overall_size = 0, new_size = 0;
+  long max_new_size;
 
   ipa_check_create_node_params ();
   ipa_check_create_edge_args ();
@@ -1183,13 +1048,13 @@ ipcp_insert_stage (void)
       {
        if (node->count > max_count)
          max_count = node->count;
-       overall_insns += node->local.inline_summary.self_insns;
+       overall_size += node->local.inline_summary.self_size;
       }
 
-  max_new_insns = overall_insns;
-  if (max_new_insns < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
-    max_new_insns = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
-  max_new_insns = max_new_insns * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
+  max_new_size = overall_size;
+  if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
+    max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
+  max_new_size = max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
 
   /* First collect all functions we proved to have constant arguments to heap.  */
   heap = fibheap_new ();
@@ -1213,6 +1078,7 @@ ipcp_insert_stage (void)
       struct ipa_node_params *info;
       int growth = 0;
       bitmap args_to_skip;
+      struct cgraph_edge *cs;
 
       node = (struct cgraph_node *)fibheap_extract_min (heap);
       node->aux = NULL;
@@ -1222,7 +1088,7 @@ ipcp_insert_stage (void)
 
       growth = ipcp_estimate_growth (node);
 
-      if (new_insns + growth > max_new_insns)
+      if (new_size + growth > max_new_size)
        break;
       if (growth
          && optimize_function_for_size_p (DECL_STRUCT_FUNCTION (node->decl)))
@@ -1232,18 +1098,24 @@ ipcp_insert_stage (void)
          continue;
        }
 
-      new_insns += growth;
+      new_size += growth;
+
+      /* Look if original function becomes dead after clonning.  */
+      for (cs = node->callers; cs != NULL; cs = cs->next_caller)
+       if (cs->caller == node || ipcp_need_redirect_p (cs))
+         break;
+      if (!cs && !node->needed)
+       bitmap_set_bit (dead_nodes, node->uid);
 
       info = IPA_NODE_REF (node);
       count = ipa_get_param_count (info);
 
-      VARRAY_GENERIC_PTR_INIT (replace_trees, ipcp_const_param_count (node),
-                               "replace_trees");
-      args_to_skip = BITMAP_ALLOC (NULL);
+      replace_trees = VEC_alloc (ipa_replace_map_p, gc, 1);
+      args_to_skip = BITMAP_GGC_ALLOC ();
       for (i = 0; i < count; i++)
        {
-         struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
-         parm_tree = ipa_get_ith_param (info, i);
+         struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
+         parm_tree = ipa_get_param (info, i);
 
          /* We can proactively remove obviously unused arguments.  */
          if (is_gimple_reg (parm_tree)
@@ -1258,7 +1130,7 @@ ipcp_insert_stage (void)
            {
              replace_param =
                ipcp_create_replace_map (parm_tree, lat);
-             VARRAY_PUSH_GENERIC_PTR (replace_trees, replace_param);
+             VEC_safe_push (ipa_replace_map_p, gc, replace_trees, replace_param);
              bitmap_set_bit (args_to_skip, i);
            }
        }
@@ -1274,20 +1146,20 @@ ipcp_insert_stage (void)
       /* Redirecting all the callers of the node to the
          new versioned node.  */
       node1 =
-       cgraph_function_versioning (node, redirect_callers, replace_trees,
-                                   args_to_skip);
-      BITMAP_FREE (args_to_skip);
+       cgraph_create_virtual_clone (node, redirect_callers, replace_trees,
+                                    args_to_skip);
+      args_to_skip = NULL;
       VEC_free (cgraph_edge_p, heap, redirect_callers);
-      VARRAY_CLEAR (replace_trees);
+      replace_trees = NULL;
+
       if (node1 == NULL)
        continue;
       if (dump_file)
        fprintf (dump_file, "versioned function %s with growth %i, overall %i\n",
-                cgraph_node_name (node), (int)growth, (int)new_insns);
+                cgraph_node_name (node), (int)growth, (int)new_size);
       ipcp_init_cloned_node (node, node1);
 
-      /* We've possibly introduced direct calls.  */
-      ipcp_update_cloned_node (node1);
+      /* TODO: We can use indirect inlning info to produce new calls.  */
 
       if (dump_file)
        dump_function_to_file (node1->decl, dump_file, dump_flags);
@@ -1365,7 +1237,7 @@ cgraph_gate_cp (void)
   return flag_ipa_cp;
 }
 
-struct ipa_opt_pass pass_ipa_cp = 
+struct ipa_opt_pass_d pass_ipa_cp =
 {
  {
   IPA_PASS,
@@ -1377,7 +1249,7 @@ struct ipa_opt_pass pass_ipa_cp =
   0,                           /* static_pass_number */
   TV_IPA_CONSTANT_PROP,                /* tv_id */
   0,                           /* properties_required */
-  PROP_trees,                  /* properties_provided */
+  0,                           /* properties_provided */
   0,                           /* properties_destroyed */
   0,                           /* todo_flags_start */
   TODO_dump_cgraph | TODO_dump_func |