OSDN Git Service

Tweak ABI & add moxie-uclinux target.
[pf3gnuchains/gcc-fork.git] / gcc / ipa-cp.c
index d6390b0..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.
@@ -351,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)
@@ -374,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",
@@ -396,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",
@@ -438,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",
@@ -676,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.  */
@@ -836,10 +876,7 @@ ipcp_update_callgraph (void)
          {
            next = cs->next_caller;
            if (!ipcp_node_is_clone (cs->caller) && ipcp_need_redirect_p (cs))
-             {
-               cgraph_redirect_edge_callee (cs, orig_node);
-               gimple_call_set_fndecl (cs->call_stmt, orig_node->decl);
-             }
+             cgraph_redirect_edge_callee (cs, orig_node);
          }
       }
 }
@@ -915,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;
@@ -955,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;
 }
@@ -1011,7 +1048,7 @@ ipcp_insert_stage (void)
       {
        if (node->count > max_count)
          max_count = node->count;
-       overall_size += node->local.inline_summary.self_insns;
+       overall_size += node->local.inline_summary.self_size;
       }
 
   max_new_size = overall_size;
@@ -1200,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,