cgraph.h (save_inline_function_body): Remove.
authorJan Hubicka <jh@suse.cz>
Tue, 19 Apr 2011 22:28:54 +0000 (00:28 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Tue, 19 Apr 2011 22:28:54 +0000 (22:28 +0000)
* cgraph.h (save_inline_function_body): Remove.
* ipa-inline-transform.c: New file, broke out of...
* ipa-inline.c: ... this one; Update toplevel comment.
(ncalls_inlined, nfunctions_inlined): Move to ipa-inline-transform.c;
make global.
(update_noncloned_frequencies): Move to ipa-inline-transform.c
(cgraph_mark_inline_edge): Rename to inline_call; move to
ipa-inline-transform.c.
(cgraph_clone_inlined_nodes): Rename to clone_inlined_nodes;
move to ipa-inline-transform.c
(recursive_inlining, inline_small_functions, flatten_function,
ipa_inline, inline_always_inline_functions,
early_inline_small_functions): Update.
(inline_transform): Move to ipa-inline-transform.c.
* ipa-inline.h (inline_call, inline_transform, clone_inlined_nodes):
Declare.
* Makefile.in (ipa-inline-transform.o): New file.
* cgraphunit.c (save_inline_function_body): Move to
ipa-inline-transform.c

From-SVN: r172739

gcc/ChangeLog
gcc/Makefile.in
gcc/cgraph.h
gcc/cgraphunit.c
gcc/ipa-inline-transform.c [new file with mode: 0644]
gcc/ipa-inline.c
gcc/ipa-inline.h

index 660f6f1f1e51d502249173e8b4b59ec6bef54085..7ba9b21c4c1701eda4883cfcaabf93a2283c4ff8 100644 (file)
@@ -1,3 +1,25 @@
+2011-04-19  Jan Hubicka  <jh@suse.cz>
+
+       * cgraph.h (save_inline_function_body): Remove.
+       * ipa-inline-transform.c: New file, broke out of...
+       * ipa-inline.c: ... this one; Update toplevel comment.
+       (ncalls_inlined, nfunctions_inlined): Move to ipa-inline-transform.c;
+       make global.
+       (update_noncloned_frequencies): Move to ipa-inline-transform.c
+       (cgraph_mark_inline_edge): Rename to inline_call; move to
+       ipa-inline-transform.c.
+       (cgraph_clone_inlined_nodes): Rename to clone_inlined_nodes;
+       move to ipa-inline-transform.c
+       (recursive_inlining, inline_small_functions, flatten_function,
+       ipa_inline, inline_always_inline_functions,
+       early_inline_small_functions): Update.
+       (inline_transform): Move to ipa-inline-transform.c.
+       * ipa-inline.h (inline_call, inline_transform, clone_inlined_nodes):
+       Declare.
+       * Makefile.in (ipa-inline-transform.o): New file.
+       * cgraphunit.c (save_inline_function_body): Move to
+       ipa-inline-transform.c
+
 2011-04-19  DJ Delorie  <dj@redhat.com>
 
        * config/m32c/m32c.c (m32c_emit_epilogue): Don't try to push
index b2d91a39c1c8a6becda910fd0aca6a031ed90c28..e300a6c8ca6c9377cf22fcc7f808774bf9bc1b07 100644 (file)
@@ -1469,6 +1469,7 @@ OBJS-archive = \
         ipa-split.o \
        ipa-inline.o \
        ipa-inline-analysis.o \
+       ipa-inline-transform.o \
        ipa-prop.o \
        ipa-pure-const.o \
        ipa-reference.o \
@@ -3035,6 +3036,11 @@ ipa-inline-analysis.o : ipa-inline-analysis.c $(CONFIG_H) $(SYSTEM_H) coretypes.
    $(DIAGNOSTIC_H) $(PARAMS_H) $(TIMEVAR_H) $(TREE_PASS_H) \
    $(HASHTAB_H) $(COVERAGE_H) $(GGC_H) $(TREE_FLOW_H) $(IPA_PROP_H) \
    gimple-pretty-print.h ipa-inline.h $(LTO_STREAMER_H)
+ipa-inline-transform.o : ipa-inline-transform.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+   $(TREE_H) langhooks.h $(TREE_INLINE_H) $(FLAGS_H) $(CGRAPH_H) intl.h \
+   $(DIAGNOSTIC_H) $(PARAMS_H) $(TIMEVAR_H) $(TREE_PASS_H) \
+   $(HASHTAB_H) $(COVERAGE_H) $(GGC_H) $(TREE_FLOW_H) $(IPA_PROP_H) \
+   gimple-pretty-print.h ipa-inline.h $(LTO_STREAMER_H)
 ipa-utils.o : ipa-utils.c $(IPA_UTILS_H) $(CONFIG_H) $(SYSTEM_H) \
    coretypes.h $(TM_H) $(TREE_H) $(TREE_FLOW_H) $(TREE_INLINE_H) langhooks.h \
    pointer-set.h $(GGC_H) $(GIMPLE_H) $(SPLAY_TREE_H) \
index a9c58798f570c1349d37e23a643f95afaf824006..032c837a228634216278cca7a1c32cd0ed353c50 100644 (file)
@@ -595,7 +595,6 @@ struct cgraph_node *cgraph_function_versioning (struct cgraph_node *,
                                                const char *);
 void tree_function_versioning (tree, tree, VEC (ipa_replace_map_p,gc)*, bool, bitmap,
                               bitmap, basic_block);
-struct cgraph_node *save_inline_function_body (struct cgraph_node *);
 void record_references_in_initializer (tree, bool);
 bool cgraph_process_new_functions (void);
 
@@ -927,7 +926,6 @@ cgraph_edge_recursive_p (struct cgraph_edge *e)
     return e->caller->decl == e->callee->decl;
 }
 
-
 /* FIXME: inappropriate dependency of cgraph on IPA.  */
 #include "ipa-ref-inline.h"
 
index 3dbfc2bbf1535d40ee3747e51b7c68bb8e3ad0c6..1a687fbbc7a938cf6abb7755407b06a45e02a731 100644 (file)
@@ -2094,74 +2094,6 @@ cgraph_function_versioning (struct cgraph_node *old_version_node,
   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, *n;
-
-  gcc_assert (node == cgraph_get_node (node->decl));
-
-  cgraph_lower_function (node);
-
-  first_clone = node->clones;
-
-  first_clone->decl = copy_node (node->decl);
-  cgraph_insert_node_to_hashtable (first_clone);
-  gcc_assert (first_clone == cgraph_get_node (first_clone->decl));
-  if (first_clone->next_sibling_clone)
-    {
-      for (n = first_clone->next_sibling_clone; n->next_sibling_clone; n = n->next_sibling_clone)
-        n->clone_of = first_clone;
-      n->clone_of = first_clone;
-      n->next_sibling_clone = first_clone->clones;
-      if (first_clone->clones)
-        first_clone->clones->prev_sibling_clone = n;
-      first_clone->clones = first_clone->next_sibling_clone;
-      first_clone->next_sibling_clone->prev_sibling_clone = NULL;
-      first_clone->next_sibling_clone = NULL;
-      gcc_assert (!first_clone->prev_sibling_clone);
-    }
-  first_clone->clone_of = NULL;
-  node->clones = NULL;
-
-  if (first_clone->clones)
-    for (n = first_clone->clones; n != first_clone;)
-      {
-        gcc_assert (n->decl == node->decl);
-       n->decl = first_clone->decl;
-       if (n->clones)
-         n = n->clones;
-       else if (n->next_sibling_clone)
-         n = n->next_sibling_clone;
-       else
-         {
-           while (n != first_clone && !n->next_sibling_clone)
-             n = n->clone_of;
-           if (n != first_clone)
-             n = n->next_sibling_clone;
-         }
-      }
-
-  /* Copy the OLD_VERSION_NODE function tree to the new version.  */
-  tree_function_versioning (node->decl, first_clone->decl, NULL, true, NULL,
-                           NULL, NULL);
-
-  DECL_EXTERNAL (first_clone->decl) = 0;
-  DECL_COMDAT_GROUP (first_clone->decl) = NULL_TREE;
-  TREE_PUBLIC (first_clone->decl) = 0;
-  DECL_COMDAT (first_clone->decl) = 0;
-  VEC_free (ipa_opt_pass, heap,
-            first_clone->ipa_transforms_to_apply);
-  first_clone->ipa_transforms_to_apply = NULL;
-
-#ifdef ENABLE_CHECKING
-  verify_cgraph_node (first_clone);
-#endif
-  return first_clone;
-}
-
 /* Given virtual clone, turn it into actual clone.  */
 static void
 cgraph_materialize_clone (struct cgraph_node *node)
diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c
new file mode 100644 (file)
index 0000000..0fb2448
--- /dev/null
@@ -0,0 +1,328 @@
+/* Callgraph transformations to handle inlining
+   Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011
+   Free Software Foundation, Inc.
+   Contributed by Jan Hubicka
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+/* The inline decisions are stored in callgraph in "inline plan" and
+   applied later.
+
+   To mark given call inline, use inline_call function.
+   The function marks the edge inlinable and, if necessary, produces
+   virtual clone in the callgraph representing the new copy of callee's
+   function body.
+
+   The inline plan is applied on given function body by inline_transform.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "langhooks.h"
+#include "cgraph.h"
+#include "timevar.h"
+#include "output.h"
+#include "intl.h"
+#include "coverage.h"
+#include "ggc.h"
+#include "tree-flow.h"
+#include "ipa-prop.h"
+#include "ipa-inline.h"
+#include "tree-inline.h"
+
+int ncalls_inlined;
+int nfunctions_inlined;
+
+/* Scale frequency of NODE edges by FREQ_SCALE and increase loop nest
+   by NEST.  */
+
+static void
+update_noncloned_frequencies (struct cgraph_node *node,
+                             int freq_scale, int nest)
+{
+  struct cgraph_edge *e;
+
+  /* We do not want to ignore high loop nest after freq drops to 0.  */
+  if (!freq_scale)
+    freq_scale = 1;
+  for (e = node->callees; e; e = e->next_callee)
+    {
+      e->loop_nest += nest;
+      e->frequency = e->frequency * (gcov_type) freq_scale / CGRAPH_FREQ_BASE;
+      if (e->frequency > CGRAPH_FREQ_MAX)
+        e->frequency = CGRAPH_FREQ_MAX;
+      if (!e->inline_failed)
+        update_noncloned_frequencies (e->callee, freq_scale, nest);
+    }
+}
+
+
+/* E is expected to be an edge being inlined.  Clone destination node of
+   the edge and redirect it to the new clone.
+   DUPLICATE is used for bookkeeping on whether we are actually creating new
+   clones or re-using node originally representing out-of-line function call.
+   */
+
+void
+clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
+                    bool update_original, int *overall_size)
+{
+  HOST_WIDE_INT peak;
+  struct inline_summary *caller_info, *callee_info;
+
+  if (duplicate)
+    {
+      /* We may eliminate the need for out-of-line copy to be output.
+        In that case just go ahead and re-use it.  This is not just an
+        memory optimization.  Making offline copy of fuction disappear
+        from the program will improve future decisions on inlining.  */
+      if (!e->callee->callers->next_caller
+         /* Recursive inlining never wants the master clone to
+            be overwritten.  */
+         && update_original
+         /* FIXME: When address is taken of DECL_EXTERNAL function we still
+            can remove its offline copy, but we would need to keep unanalyzed
+            node in the callgraph so references can point to it.  */
+         && !e->callee->address_taken
+         && cgraph_can_remove_if_no_direct_calls_p (e->callee)
+         /* Inlining might enable more devirtualizing, so we want to remove
+            those only after all devirtualizable virtual calls are processed.
+            Lacking may edges in callgraph we just preserve them post
+            inlining.  */
+         && (!DECL_VIRTUAL_P (e->callee->decl)
+             || (!DECL_COMDAT (e->callee->decl)
+                 && !DECL_EXTERNAL (e->callee->decl)))
+         /* Don't reuse if more than one function shares a comdat group.
+            If the other function(s) are needed, we need to emit even
+            this function out of line.  */
+         && !e->callee->same_comdat_group
+         /* During early inlining some unanalyzed cgraph nodes might be in the
+            callgraph and they might reffer the function in question.  */
+         && !cgraph_new_nodes)
+       {
+         gcc_assert (!e->callee->global.inlined_to);
+         if (e->callee->analyzed && !DECL_EXTERNAL (e->callee->decl))
+           {
+             if (overall_size)
+               *overall_size -= inline_summary (e->callee)->size;
+             nfunctions_inlined++;
+           }
+         duplicate = false;
+         e->callee->local.externally_visible = false;
+          update_noncloned_frequencies (e->callee, e->frequency, e->loop_nest);
+       }
+      else
+       {
+         struct cgraph_node *n;
+         n = cgraph_clone_node (e->callee, e->callee->decl,
+                                e->count, e->frequency, e->loop_nest,
+                                update_original, NULL);
+         cgraph_redirect_edge_callee (e, n);
+       }
+    }
+
+  callee_info = inline_summary (e->callee);
+  caller_info = inline_summary (e->caller);
+
+  if (e->caller->global.inlined_to)
+    e->callee->global.inlined_to = e->caller->global.inlined_to;
+  else
+    e->callee->global.inlined_to = e->caller;
+  callee_info->stack_frame_offset
+    = caller_info->stack_frame_offset
+      + caller_info->estimated_self_stack_size;
+  peak = callee_info->stack_frame_offset
+      + callee_info->estimated_self_stack_size;
+  if (inline_summary (e->callee->global.inlined_to)->estimated_stack_size
+      < peak)
+    inline_summary (e->callee->global.inlined_to)->estimated_stack_size = peak;
+  cgraph_propagate_frequency (e->callee);
+
+  /* Recursively clone all bodies.  */
+  for (e = e->callee->callees; e; e = e->next_callee)
+    if (!e->inline_failed)
+      clone_inlined_nodes (e, duplicate, update_original, overall_size);
+}
+
+
+/* Mark edge E as inlined and update callgraph accordingly.  UPDATE_ORIGINAL
+   specify whether profile of original function should be updated.  If any new
+   indirect edges are discovered in the process, add them to NEW_EDGES, unless
+   it is NULL.  Return true iff any new callgraph edges were discovered as a
+   result of inlining.  */
+
+bool
+inline_call (struct cgraph_edge *e, bool update_original,
+            VEC (cgraph_edge_p, heap) **new_edges,
+            int *overall_size)
+{
+  int old_size = 0, new_size = 0;
+  struct cgraph_node *to = NULL;
+  struct cgraph_edge *curr = e;
+  struct inline_summary *info;
+
+  /* Don't inline inlined edges.  */
+  gcc_assert (e->inline_failed);
+  /* Don't even think of inlining inline clone.  */
+  gcc_assert (!e->callee->global.inlined_to);
+
+  e->inline_failed = CIF_OK;
+  DECL_POSSIBLY_INLINED (e->callee->decl) = true;
+
+  clone_inlined_nodes (e, true, update_original, overall_size);
+
+  /* Now update size of caller and all functions caller is inlined into.  */
+  for (;e && !e->inline_failed; e = e->caller->callers)
+    {
+      to = e->caller;
+      info = inline_summary (to);
+      old_size = info->size;
+      new_size = estimate_size_after_inlining (to, curr);
+      info->size = new_size;
+      info->time = estimate_time_after_inlining (to, curr);
+    }
+  gcc_assert (curr->callee->global.inlined_to == to);
+  if (overall_size && new_size > old_size)
+    *overall_size += new_size - old_size;
+  ncalls_inlined++;
+
+  if (flag_indirect_inlining && optimize)
+    return ipa_propagate_indirect_call_infos (curr, new_edges);
+  else
+    return false;
+}
+
+
+/* Copy function body of NODE and redirect all inline clones to it.
+   This is done before inline plan is applied to NODE when there are
+   still some inline clones if it.
+
+   This is neccesary because inline decisions are not really transitive
+   and the other inline clones may have different bodies.  */
+
+static struct cgraph_node *
+save_inline_function_body (struct cgraph_node *node)
+{
+  struct cgraph_node *first_clone, *n;
+
+  if (dump_file)
+    fprintf (dump_file, "\nSaving body of %s for later reuse\n",
+            cgraph_node_name (node));
+  gcc_assert (node == cgraph_get_node (node->decl));
+
+  /* first_clone will be turned into real function.  */
+  first_clone = node->clones;
+  first_clone->decl = copy_node (node->decl);
+  cgraph_insert_node_to_hashtable (first_clone);
+  gcc_assert (first_clone == cgraph_get_node (first_clone->decl));
+
+  /* Now reshape the clone tree, so all other clones descends from
+     first_clone.  */
+  if (first_clone->next_sibling_clone)
+    {
+      for (n = first_clone->next_sibling_clone; n->next_sibling_clone; n = n->next_sibling_clone)
+        n->clone_of = first_clone;
+      n->clone_of = first_clone;
+      n->next_sibling_clone = first_clone->clones;
+      if (first_clone->clones)
+        first_clone->clones->prev_sibling_clone = n;
+      first_clone->clones = first_clone->next_sibling_clone;
+      first_clone->next_sibling_clone->prev_sibling_clone = NULL;
+      first_clone->next_sibling_clone = NULL;
+      gcc_assert (!first_clone->prev_sibling_clone);
+    }
+  first_clone->clone_of = NULL;
+
+  /* Now node in question has no clones.  */
+  node->clones = NULL;
+
+  if (first_clone->clones)
+    for (n = first_clone->clones; n != first_clone;)
+      {
+        gcc_assert (n->decl == node->decl);
+       n->decl = first_clone->decl;
+       if (n->clones)
+         n = n->clones;
+       else if (n->next_sibling_clone)
+         n = n->next_sibling_clone;
+       else
+         {
+           while (n != first_clone && !n->next_sibling_clone)
+             n = n->clone_of;
+           if (n != first_clone)
+             n = n->next_sibling_clone;
+         }
+      }
+
+  /* Copy the OLD_VERSION_NODE function tree to the new version.  */
+  tree_function_versioning (node->decl, first_clone->decl, NULL, true, NULL,
+                           NULL, NULL);
+
+  DECL_EXTERNAL (first_clone->decl) = 0;
+  DECL_COMDAT_GROUP (first_clone->decl) = NULL_TREE;
+  TREE_PUBLIC (first_clone->decl) = 0;
+  DECL_COMDAT (first_clone->decl) = 0;
+  VEC_free (ipa_opt_pass, heap,
+            first_clone->ipa_transforms_to_apply);
+  first_clone->ipa_transforms_to_apply = NULL;
+
+#ifdef ENABLE_CHECKING
+  verify_cgraph_node (first_clone);
+#endif
+  return first_clone;
+}
+
+
+/* Apply inline plan to function.  */
+
+unsigned int
+inline_transform (struct cgraph_node *node)
+{
+  unsigned int todo = 0;
+  struct cgraph_edge *e;
+  bool inline_p = false;
+
+  /* FIXME: Currently the pass manager is adding inline transform more than
+     once to some clones.  This needs revisiting after WPA cleanups.  */
+  if (cfun->after_inlining)
+    return 0;
+
+  /* We might need the body of this function so that we can expand
+     it inline somewhere else.  */
+  if (cgraph_preserve_function_body_p (node->decl))
+    save_inline_function_body (node);
+
+  for (e = node->callees; e; e = e->next_callee)
+    {
+      cgraph_redirect_edge_call_stmt_to_callee (e);
+      if (!e->inline_failed || warn_inline)
+        inline_p = true;
+    }
+
+  if (inline_p)
+    {
+      timevar_push (TV_INTEGRATION);
+      todo = optimize_inline_calls (current_function_decl);
+      timevar_pop (TV_INTEGRATION);
+    }
+  cfun->always_inline_functions_inlined = true;
+  cfun->after_inlining = true;
+  return todo | execute_fixup_cfg ();
+}
index d1928883140f26a970dd8fe2c266d7c4c1e571ad..5140cfa744cdb114bb9b2941e96e043e41395ada 100644 (file)
@@ -23,18 +23,6 @@ along with GCC; see the file COPYING3.  If not see
 
     The implementation of inliner is organized as follows:
 
-    Transformation of callgraph to represent inlining decisions.
-
-      The inline decisions are stored in callgraph in "inline plan" and
-      all applied later.
-
-      To mark given call inline, use cgraph_mark_inline function.
-      The function marks the edge inlinable and, if necessary, produces
-      virtual clone in the callgraph representing the new copy of callee's
-      function body.
-
-      The inline plan is applied on given function body by inline_transform. 
-
     inlining heuristics limits
 
       can_inline_edge_p allow to check that particular inlining is allowed
@@ -128,163 +116,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "ipa-inline.h"
 
 /* Statistics we collect about inlining algorithm.  */
-static int ncalls_inlined;
-static int nfunctions_inlined;
 static int overall_size;
 static gcov_type max_count, max_benefit;
 
-/* Scale frequency of NODE edges by FREQ_SCALE and increase loop nest
-   by NEST.  */
-
-static void
-update_noncloned_frequencies (struct cgraph_node *node,
-                             int freq_scale, int nest)
-{
-  struct cgraph_edge *e;
-
-  /* We do not want to ignore high loop nest after freq drops to 0.  */
-  if (!freq_scale)
-    freq_scale = 1;
-  for (e = node->callees; e; e = e->next_callee)
-    {
-      e->loop_nest += nest;
-      e->frequency = e->frequency * (gcov_type) freq_scale / CGRAPH_FREQ_BASE;
-      if (e->frequency > CGRAPH_FREQ_MAX)
-        e->frequency = CGRAPH_FREQ_MAX;
-      if (!e->inline_failed)
-        update_noncloned_frequencies (e->callee, freq_scale, nest);
-    }
-}
-
-/* E is expected to be an edge being inlined.  Clone destination node of
-   the edge and redirect it to the new clone.
-   DUPLICATE is used for bookkeeping on whether we are actually creating new
-   clones or re-using node originally representing out-of-line function call.
-   */
-void
-cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
-                           bool update_original)
-{
-  HOST_WIDE_INT peak;
-  struct inline_summary *caller_info, *callee_info;
-
-  if (duplicate)
-    {
-      /* We may eliminate the need for out-of-line copy to be output.
-        In that case just go ahead and re-use it.  */
-      if (!e->callee->callers->next_caller
-         /* Recursive inlining never wants the master clone to
-            be overwritten.  */
-         && update_original
-         /* FIXME: When address is taken of DECL_EXTERNAL function we still
-            can remove its offline copy, but we would need to keep unanalyzed
-            node in the callgraph so references can point to it.  */
-         && !e->callee->address_taken
-         && cgraph_can_remove_if_no_direct_calls_p (e->callee)
-         /* Inlining might enable more devirtualizing, so we want to remove
-            those only after all devirtualizable virtual calls are processed.
-            Lacking may edges in callgraph we just preserve them post
-            inlining.  */
-         && (!DECL_VIRTUAL_P (e->callee->decl)
-             || (!DECL_COMDAT (e->callee->decl)
-                 && !DECL_EXTERNAL (e->callee->decl)))
-         /* Don't reuse if more than one function shares a comdat group.
-            If the other function(s) are needed, we need to emit even
-            this function out of line.  */
-         && !e->callee->same_comdat_group
-         && !cgraph_new_nodes)
-       {
-         gcc_assert (!e->callee->global.inlined_to);
-         if (e->callee->analyzed && !DECL_EXTERNAL (e->callee->decl))
-           {
-             overall_size -= inline_summary (e->callee)->size;
-             nfunctions_inlined++;
-           }
-         duplicate = false;
-         e->callee->local.externally_visible = false;
-          update_noncloned_frequencies (e->callee, e->frequency, e->loop_nest);
-       }
-      else
-       {
-         struct cgraph_node *n;
-         n = cgraph_clone_node (e->callee, e->callee->decl,
-                                e->count, e->frequency, e->loop_nest,
-                                update_original, NULL);
-         cgraph_redirect_edge_callee (e, n);
-       }
-    }
-
-  callee_info = inline_summary (e->callee);
-  caller_info = inline_summary (e->caller);
-
-  if (e->caller->global.inlined_to)
-    e->callee->global.inlined_to = e->caller->global.inlined_to;
-  else
-    e->callee->global.inlined_to = e->caller;
-  callee_info->stack_frame_offset
-    = caller_info->stack_frame_offset
-      + caller_info->estimated_self_stack_size;
-  peak = callee_info->stack_frame_offset
-      + callee_info->estimated_self_stack_size;
-  if (inline_summary (e->callee->global.inlined_to)->estimated_stack_size
-      < peak)
-    inline_summary (e->callee->global.inlined_to)->estimated_stack_size = peak;
-  cgraph_propagate_frequency (e->callee);
-
-  /* Recursively clone all bodies.  */
-  for (e = e->callee->callees; e; e = e->next_callee)
-    if (!e->inline_failed)
-      cgraph_clone_inlined_nodes (e, duplicate, update_original);
-}
-
-/* Mark edge E as inlined and update callgraph accordingly.  UPDATE_ORIGINAL
-   specify whether profile of original function should be updated.  If any new
-   indirect edges are discovered in the process, add them to NEW_EDGES, unless
-   it is NULL.  Return true iff any new callgraph edges were discovered as a
-   result of inlining.  */
-
-static bool
-cgraph_mark_inline_edge (struct cgraph_edge *e, bool update_original,
-                        VEC (cgraph_edge_p, heap) **new_edges)
-{
-  int old_size = 0, new_size = 0;
-  struct cgraph_node *to = NULL;
-  struct cgraph_edge *curr = e;
-  struct inline_summary *info;
-
-  /* Don't inline inlined edges.  */
-  gcc_assert (e->inline_failed);
-  /* Don't even think of inlining inline clone.  */
-  gcc_assert (!e->callee->global.inlined_to);
-
-  e->inline_failed = CIF_OK;
-  DECL_POSSIBLY_INLINED (e->callee->decl) = true;
-
-  cgraph_clone_inlined_nodes (e, true, update_original);
-
-  /* Now update size of caller and all functions caller is inlined into.  */
-  for (;e && !e->inline_failed; e = e->caller->callers)
-    {
-      to = e->caller;
-      info = inline_summary (to);
-      old_size = info->size;
-      new_size = estimate_size_after_inlining (to, curr);
-      info->size = new_size;
-      info->time = estimate_time_after_inlining (to, curr);
-    }
-  gcc_assert (curr->callee->global.inlined_to == to);
-  if (new_size > old_size)
-    overall_size += new_size - old_size;
-  ncalls_inlined++;
-
-  /* FIXME: We should remove the optimize check after we ensure we never run
-     IPA passes when not optimizing.  */
-  if (flag_indirect_inlining && optimize)
-    return ipa_propagate_indirect_call_infos (curr, new_edges);
-  else
-    return false;
-}
-
 /* Return false when inlining edge E would lead to violating
    limits on function unit growth or stack usage growth.  
 
@@ -1196,11 +1030,11 @@ recursive_inlining (struct cgraph_edge *edge,
                                            false, NULL);
          for (e = master_clone->callees; e; e = e->next_callee)
            if (!e->inline_failed)
-             cgraph_clone_inlined_nodes (e, true, false);
+             clone_inlined_nodes (e, true, false, NULL);
        }
 
       cgraph_redirect_edge_callee (curr, master_clone);
-      cgraph_mark_inline_edge (curr, false, new_edges);
+      inline_call (curr, false, new_edges, &overall_size);
       lookup_recursive_calls (node, curr->callee, heap);
       n++;
     }
@@ -1460,7 +1294,7 @@ inline_small_functions (void)
 
          callee = edge->callee;
          gcc_checking_assert (!callee->global.inlined_to);
-         cgraph_mark_inline_edge (edge, true, &new_indirect_edges);
+         inline_call (edge, true, &new_indirect_edges, &overall_size);
          if (flag_indirect_inlining)
            add_new_edges_to_heap (heap, new_indirect_edges);
 
@@ -1588,7 +1422,7 @@ flatten_function (struct cgraph_node *node)
                 cgraph_node_name (e->callee),
                 cgraph_node_name (e->caller));
       orig_callee = e->callee;
-      cgraph_mark_inline_edge (e, true, NULL);
+      inline_call (e, true, NULL, NULL);
       if (e->callee != orig_callee)
        orig_callee->aux = (void *) node;
       flatten_function (e->callee);
@@ -1697,7 +1531,7 @@ ipa_inline (void)
                               inline_summary (node->callers->caller)->size);
                    }
 
-                 cgraph_mark_inline_edge (node->callers, true, NULL);
+                 inline_call (node->callers, true, NULL, NULL);
                  if (dump_file)
                    fprintf (dump_file,
                             " Inlined into %s which now has %i size\n",
@@ -1752,7 +1586,7 @@ inline_always_inline_functions (struct cgraph_node *node)
        fprintf (dump_file, "  Inlining %s into %s (always_inline).\n",
                 cgraph_node_name (e->callee),
                 cgraph_node_name (e->caller));
-      cgraph_mark_inline_edge (e, true, NULL);
+      inline_call (e, true, NULL, NULL);
       inlined = true;
     }
 
@@ -1801,7 +1635,7 @@ early_inline_small_functions (struct cgraph_node *node)
        fprintf (dump_file, " Inlining %s into %s.\n",
                 cgraph_node_name (e->callee),
                 cgraph_node_name (e->caller));
-      cgraph_mark_inline_edge (e, true, NULL);
+      inline_call (e, true, NULL, NULL);
       inlined = true;
     }
 
@@ -1916,42 +1750,6 @@ struct gimple_opt_pass pass_early_inline =
 };
 
 
-/* Apply inline plan to function.  */
-static unsigned int
-inline_transform (struct cgraph_node *node)
-{
-  unsigned int todo = 0;
-  struct cgraph_edge *e;
-  bool inline_p = false;
-
-  /* FIXME: Currently the pass manager is adding inline transform more than
-     once to some clones.  This needs revisiting after WPA cleanups.  */
-  if (cfun->after_inlining)
-    return 0;
-
-  /* We might need the body of this function so that we can expand
-     it inline somewhere else.  */
-  if (cgraph_preserve_function_body_p (node->decl))
-    save_inline_function_body (node);
-
-  for (e = node->callees; e; e = e->next_callee)
-    {
-      cgraph_redirect_edge_call_stmt_to_callee (e);
-      if (!e->inline_failed || warn_inline)
-        inline_p = true;
-    }
-
-  if (inline_p)
-    {
-      timevar_push (TV_INTEGRATION);
-      todo = optimize_inline_calls (current_function_decl);
-      timevar_pop (TV_INTEGRATION);
-    }
-  cfun->always_inline_functions_inlined = true;
-  cfun->after_inlining = true;
-  return todo | execute_fixup_cfg ();
-}
-
 /* When to run IPA inlining.  Inlining of always-inline functions
    happens during early inlining.  */
 
index 1fd1f5c9ff560eb1f171e08da27f6326e2806cb3..48415e6eea2e2953dc3770b6c25332fb8dbf1df0 100644 (file)
@@ -63,6 +63,7 @@ DEF_VEC_O(inline_summary_t);
 DEF_VEC_ALLOC_O(inline_summary_t,heap);
 extern VEC(inline_summary_t,heap) *inline_summary_vec;
 
+/* In ipa-inline-analysis.c  */
 void debug_inline_summary (struct cgraph_node *);
 void dump_inline_summaries (FILE *f);
 void inline_generate_summary (void);
@@ -74,6 +75,14 @@ int estimate_time_after_inlining (struct cgraph_node *, struct cgraph_edge *);
 int estimate_size_after_inlining (struct cgraph_node *, struct cgraph_edge *);
 int estimate_growth (struct cgraph_node *);
 
+/* In ipa-inline-transform.c  */
+bool inline_call (struct cgraph_edge *, bool, VEC (cgraph_edge_p, heap) **, int *);
+unsigned int inline_transform (struct cgraph_node *);
+void clone_inlined_nodes (struct cgraph_edge *e, bool, bool, int *);
+
+extern int ncalls_inlined;
+extern int nfunctions_inlined;
+
 static inline struct inline_summary *
 inline_summary (struct cgraph_node *node)
 {