cgraph.c (dump_cgraph_node): Do not dump inline summaries.
authorJan Hubicka <jh@suse.cz>
Thu, 14 Apr 2011 13:26:44 +0000 (15:26 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Thu, 14 Apr 2011 13:26:44 +0000 (13:26 +0000)
* cgraph.c (dump_cgraph_node): Do not dump inline summaries.
* cgraph.h (struct inline_summary): Move to ipa-inline.h
(cgraph_local_info): Remove inline_summary.
* ipa-cp.c: Include ipa-inline.h.
(ipcp_cloning_candidate_p, ipcp_estimate_growth,
ipcp_estimate_cloning_cost, ipcp_insert_stage): Use inline_summary
accesor.
* lto-cgraph.c (lto_output_node): Do not stream inline summary.
(input_overwrite_node): Do not set inline summary.
(input_node): Do not stream inline summary.
* ipa-inline.c (cgraph_decide_inlining): Dump inline summaries.
(cgraph_decide_inlining_incrementally): Do not try to estimate overall
growth; we do not have inline parameters computed for that anyway.
(cgraph_early_inlining): After inlining compute call_stmt_sizes.
* ipa-inline.h (struct inline_summary): Move here from ipa-inline.h
(inline_summary_t): New type and VECtor.
(debug_inline_summary, dump_inline_summaries): Declare.
(inline_summary): Use VOCtor.
(estimate_edge_growth): Kill hack computing call stmt size directly.
* lto-section-in.c (lto_section_name): Add inline section.
* ipa-inline-analysis.c: Include lto-streamer.h
(node_removal_hook_holder, node_duplication_hook_holder): New holders
(inline_node_removal_hook, inline_node_duplication_hook): New functions.
(inline_summary_vec): Define.
(inline_summary_alloc, dump_inline_summary, debug_inline_summary,
dump_inline_summaries): New functions.
(estimate_function_body_sizes): Properly compute size/time of outgoing calls.
(compute_inline_parameters): Alloc inline_summary; do not compute size/time
of incomming calls.
(estimate_edge_time): Avoid missing time summary hack.
(inline_read_summary): Read inline summary info.
(inline_write_summary): Write inline summary info.
(inline_free_summary): Free all hooks and inline summary vector.
* lto-streamer.h: Add LTO_section_inline_summary section.
* Makefile.in (ipa-cp.o, ipa-inline-analysis.o): Update dependencies.
* ipa.c (cgraph_remove_unreachable_nodes): Fix dump file formating.

* lto.c: Include ipa-inline.h
(add_cgraph_node_to_partition, undo_partition): Use inline_summary accessor.
(ipa_node_duplication_hook): Fix declaration.
* Make-lang.in (lto.o): Update dependencies.

From-SVN: r172430

16 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/cgraph.c
gcc/cgraph.h
gcc/ipa-cp.c
gcc/ipa-inline-analysis.c
gcc/ipa-inline.c
gcc/ipa-inline.h
gcc/ipa-prop.c
gcc/ipa.c
gcc/lto-cgraph.c
gcc/lto-section-in.c
gcc/lto-streamer.h
gcc/lto/ChangeLog
gcc/lto/Make-lang.in
gcc/lto/lto.c

index 38bff669124f7d6de98b1796195d19c952afdbab..be9ccb246b5a9a5404763c1a3d0fea7733805abf 100644 (file)
@@ -1,3 +1,42 @@
+2011-04-14  Jan Hubicka  <jh@suse.cz>
+
+       * cgraph.c (dump_cgraph_node): Do not dump inline summaries.
+       * cgraph.h (struct inline_summary): Move to ipa-inline.h
+       (cgraph_local_info): Remove inline_summary.
+       * ipa-cp.c: Include ipa-inline.h.
+       (ipcp_cloning_candidate_p, ipcp_estimate_growth,
+       ipcp_estimate_cloning_cost, ipcp_insert_stage): Use inline_summary
+       accesor.
+       * lto-cgraph.c (lto_output_node): Do not stream inline summary.
+       (input_overwrite_node): Do not set inline summary.
+       (input_node): Do not stream inline summary.
+       * ipa-inline.c (cgraph_decide_inlining): Dump inline summaries.
+       (cgraph_decide_inlining_incrementally): Do not try to estimate overall
+       growth; we do not have inline parameters computed for that anyway.
+       (cgraph_early_inlining): After inlining compute call_stmt_sizes.
+       * ipa-inline.h (struct inline_summary): Move here from ipa-inline.h
+       (inline_summary_t): New type and VECtor.
+       (debug_inline_summary, dump_inline_summaries): Declare.
+       (inline_summary): Use VOCtor.
+       (estimate_edge_growth): Kill hack computing call stmt size directly.
+       * lto-section-in.c (lto_section_name): Add inline section.
+       * ipa-inline-analysis.c: Include lto-streamer.h
+       (node_removal_hook_holder, node_duplication_hook_holder): New holders
+       (inline_node_removal_hook, inline_node_duplication_hook): New functions.
+       (inline_summary_vec): Define.
+       (inline_summary_alloc, dump_inline_summary, debug_inline_summary,
+       dump_inline_summaries): New functions.
+       (estimate_function_body_sizes): Properly compute size/time of outgoing calls.
+       (compute_inline_parameters): Alloc inline_summary; do not compute size/time
+       of incomming calls.
+       (estimate_edge_time): Avoid missing time summary hack.
+       (inline_read_summary): Read inline summary info.
+       (inline_write_summary): Write inline summary info.
+       (inline_free_summary): Free all hooks and inline summary vector.
+       * lto-streamer.h: Add LTO_section_inline_summary section.
+       * Makefile.in (ipa-cp.o, ipa-inline-analysis.o): Update dependencies.
+       * ipa.c (cgraph_remove_unreachable_nodes): Fix dump file formating.
+
 2011-04-14  Richard Sandiford  <richard.sandiford@linaro.org>
 
        * tree-vectorizer.h (vect_strided_store_supported): Add a
index 1a0d98d2625167208de636f5cae50a7427bac936..04b10cd8cd920b47bc5c90218a66c0709467db27 100644 (file)
@@ -3011,7 +3011,7 @@ ipa-ref.o : ipa-ref.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
 ipa-cp.o : ipa-cp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h  \
    $(TREE_H) $(TARGET_H) $(GIMPLE_H) $(CGRAPH_H) $(IPA_PROP_H) $(TREE_FLOW_H) \
    $(TREE_PASS_H) $(FLAGS_H) $(TIMEVAR_H) $(DIAGNOSTIC_H) $(TREE_DUMP_H) \
-   $(TREE_INLINE_H) $(FIBHEAP_H) $(PARAMS_H) tree-pretty-print.h
+   $(TREE_INLINE_H) $(FIBHEAP_H) $(PARAMS_H) tree-pretty-print.h ipa-inline.h
 ipa-split.o : ipa-split.c $(CONFIG_H) $(SYSTEM_H) coretypes.h  \
    $(TREE_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) $(TREE_FLOW_H) \
    $(TREE_PASS_H) $(FLAGS_H) $(TIMEVAR_H) $(DIAGNOSTIC_H) $(TREE_DUMP_H) \
@@ -3032,7 +3032,7 @@ ipa-inline-analysis.o : ipa-inline-analysis.c $(CONFIG_H) $(SYSTEM_H) coretypes.
    $(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
+   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 22098e54955d848fc620c9c885220968c6cf1a99..09436c7cfb575c4653f93e7094a050c348468d8f 100644 (file)
@@ -1876,22 +1876,6 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
   if (node->count)
     fprintf (f, " executed "HOST_WIDEST_INT_PRINT_DEC"x",
             (HOST_WIDEST_INT)node->count);
-  if (node->local.inline_summary.self_time)
-    fprintf (f, " %i time, %i benefit", node->local.inline_summary.self_time,
-                                       node->local.inline_summary.time_inlining_benefit);
-  if (node->global.time && node->global.time
-      != node->local.inline_summary.self_time)
-    fprintf (f, " (%i after inlining)", node->global.time);
-  if (node->local.inline_summary.self_size)
-    fprintf (f, " %i size, %i benefit", node->local.inline_summary.self_size,
-                                       node->local.inline_summary.size_inlining_benefit);
-  if (node->global.size && node->global.size
-      != node->local.inline_summary.self_size)
-    fprintf (f, " (%i after inlining)", node->global.size);
-  if (node->local.inline_summary.estimated_self_stack_size)
-    fprintf (f, " %i bytes stack usage", (int)node->local.inline_summary.estimated_self_stack_size);
-  if (node->global.estimated_stack_size != node->local.inline_summary.estimated_self_stack_size)
-    fprintf (f, " %i bytes after inlining", (int)node->global.estimated_stack_size);
   if (node->origin)
     fprintf (f, " nested in: %s", cgraph_node_name (node->origin));
   if (node->needed)
index 135164205ce9ead1df13b17634bbed1a8dc75530..eb5154638bc8fd653164a0c6f1891b159e62fc8f 100644 (file)
@@ -58,23 +58,6 @@ struct lto_file_decl_data;
 extern const char * const cgraph_availability_names[];
 extern const char * const ld_plugin_symbol_resolution_names[];
 
-/* Function inlining information.  */
-
-struct GTY(()) inline_summary
-{
-  /* Estimated stack frame consumption by the function.  */
-  HOST_WIDE_INT estimated_self_stack_size;
-
-  /* Size of the function body.  */
-  int self_size;
-  /* How many instructions are likely going to disappear after inlining.  */
-  int size_inlining_benefit;
-  /* Estimated time spent executing the function body.  */
-  int self_time;
-  /* How much time is going to be saved by inlining.  */
-  int time_inlining_benefit;
-};
-
 /* Information about thunk, used only for same body aliases.  */
 
 struct GTY(()) cgraph_thunk_info {
@@ -95,8 +78,6 @@ struct GTY(()) cgraph_local_info {
   /* File stream where this node is being written to.  */
   struct lto_file_decl_data * lto_file_data;
 
-  struct inline_summary inline_summary;
-
   /* Set when function function is visible in current compilation unit only
      and its address is never taken.  */
   unsigned local : 1;
index a2928dbee6c55ea72ba70911b19609b44e57f138..4cee1d481e66bdcb711795b52b77c85a99d1c77d 100644 (file)
@@ -148,6 +148,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-inline.h"
 #include "fibheap.h"
 #include "params.h"
+#include "ipa-inline.h"
 
 /* Number of functions identified as candidates for cloning. When not cloning
    we can simplify iterate stage not forcing it to go through the decision
@@ -495,7 +496,7 @@ ipcp_cloning_candidate_p (struct cgraph_node *node)
                 cgraph_node_name (node));
       return false;
     }
-  if (node->local.inline_summary.self_size < n_calls)
+  if (inline_summary (node)->self_size < n_calls)
     {
       if (dump_file)
         fprintf (dump_file, "Considering %s for cloning; code would shrink.\n",
@@ -1189,7 +1190,7 @@ ipcp_estimate_growth (struct cgraph_node *node)
      call site.  Precise cost is difficult 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_size
+  growth = inline_summary (node)->self_size
           - removable_args * redirectable_node_callers;
   if (growth < 0)
     return 0;
@@ -1229,7 +1230,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_size,
+             cgraph_node_name (node), cost, inline_summary (node)->self_size,
             freq_sum);
   return cost + 1;
 }
@@ -1364,7 +1365,7 @@ ipcp_insert_stage (void)
       {
        if (node->count > max_count)
          max_count = node->count;
-       overall_size += node->local.inline_summary.self_size;
+       overall_size += inline_summary (node)->self_size;
       }
 
   max_new_size = overall_size;
index 8507c5e27d78170ee181ce569451daa4924956a5..47bd2a8c1da1ab4ed4a64b89077786a3e402f020 100644 (file)
@@ -23,13 +23,13 @@ along with GCC; see the file COPYING3.  If not see
 
    We estimate for each function
      - function body size
-     - function runtime
+     - average function execution time
      - inlining size benefit (that is how much of function body size
        and its call sequence is expected to disappear by inlining)
      - inlining time benefit
      - function frame size
    For each call
-     - call sequence size
+     - call statement size and time
 
    inlinie_summary datastructures store above information locally (i.e.
    parameters of the function itself) and globally (i.e. parameters of
@@ -61,12 +61,99 @@ along with GCC; see the file COPYING3.  If not see
 #include "ggc.h"
 #include "tree-flow.h"
 #include "ipa-prop.h"
+#include "lto-streamer.h"
 #include "ipa-inline.h"
 
 #define MAX_TIME 1000000000
 
 /* Holders of ipa cgraph hooks: */
 static struct cgraph_node_hook_list *function_insertion_hook_holder;
+static struct cgraph_node_hook_list *node_removal_hook_holder;
+static struct cgraph_2node_hook_list *node_duplication_hook_holder;
+static void inline_node_removal_hook (struct cgraph_node *, void *);
+static void inline_node_duplication_hook (struct cgraph_node *,
+                                         struct cgraph_node *, void *);
+
+/* VECtor holding inline summaries.  */
+VEC(inline_summary_t,heap) *inline_summary_vec;
+
+/* Allocate the inline summary vector or resize it to cover all cgraph nodes. */
+
+static void
+inline_summary_alloc (void)
+{
+  if (!node_removal_hook_holder)
+    node_removal_hook_holder =
+      cgraph_add_node_removal_hook (&inline_node_removal_hook, NULL);
+  if (!node_duplication_hook_holder)
+    node_duplication_hook_holder =
+      cgraph_add_node_duplication_hook (&inline_node_duplication_hook, NULL);
+
+  if (VEC_length (inline_summary_t, inline_summary_vec)
+      <= (unsigned) cgraph_max_uid)
+    VEC_safe_grow_cleared (inline_summary_t, heap,
+                          inline_summary_vec, cgraph_max_uid + 1);
+}
+
+/* Hook that is called by cgraph.c when a node is removed.  */
+
+static void
+inline_node_removal_hook (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
+{
+  if (VEC_length (inline_summary_t, inline_summary_vec)
+      <= (unsigned)node->uid)
+    return;
+  memset (inline_summary (node),
+         0, sizeof (inline_summary_t));
+}
+
+/* Hook that is called by cgraph.c when a node is duplicated.  */
+
+static void
+inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
+                             ATTRIBUTE_UNUSED void *data)
+{
+  inline_summary_alloc ();
+  memcpy (inline_summary (dst), inline_summary (src),
+         sizeof (struct inline_summary));
+}
+
+static void
+dump_inline_summary (FILE *f, struct cgraph_node *node)
+{
+  if (node->analyzed)
+    {
+      struct inline_summary *s = inline_summary (node);
+      fprintf (f, "Inline summary for %s/%i\n", cgraph_node_name (node),
+              node->uid);
+      fprintf (f, "  self time:       %i, benefit: %i\n",
+              s->self_time, s->time_inlining_benefit);
+      fprintf (f, "  global time:     %i\n", node->global.time);
+      fprintf (f, "  self size:       %i, benefit: %i\n",
+              s->self_size, s->size_inlining_benefit);
+      fprintf (f, "  global size:     %i", node->global.size);
+      fprintf (f, "  self stack:      %i\n",
+              (int)s->estimated_self_stack_size);
+      fprintf (f, "  global stack:    %i\n\n",
+              (int)node->global.estimated_stack_size);
+    }
+}
+
+void
+debug_inline_summary (struct cgraph_node *node)
+{
+  dump_inline_summary (stderr, node);
+}
+
+void
+dump_inline_summaries (FILE *f)
+{
+  struct cgraph_node *node;
+
+  for (node = cgraph_nodes; node; node = node->next)
+    if (node->analyzed)
+      dump_inline_summary (f, node);
+}
 
 /* See if statement might disappear after inlining.
    0 - means not eliminated
@@ -179,16 +266,27 @@ estimate_function_body_sizes (struct cgraph_node *node)
                       freq, this_size, this_time);
              print_gimple_stmt (dump_file, stmt, 0, 0);
            }
+
+         if (is_gimple_call (stmt))
+           {
+             struct cgraph_edge *edge = cgraph_edge (node, stmt);
+             edge->call_stmt_size = this_size;
+             edge->call_stmt_time = this_time;
+           }
+
          this_time *= freq;
          time += this_time;
          size += this_size;
+
          prob = eliminated_by_inlining_prob (stmt);
          if (prob == 1 && dump_file && (dump_flags & TDF_DETAILS))
            fprintf (dump_file, "    50%% will be eliminated by inlining\n");
          if (prob == 2 && dump_file && (dump_flags & TDF_DETAILS))
            fprintf (dump_file, "    will eliminated by inlining\n");
+
          size_inlining_benefit += this_size * prob;
          time_inlining_benefit += this_time * prob;
+
          gcc_assert (time >= 0);
          gcc_assert (size >= 0);
        }
@@ -222,6 +320,8 @@ compute_inline_parameters (struct cgraph_node *node)
 
   gcc_assert (!node->global.inlined_to);
 
+  inline_summary_alloc ();
+
   /* Estimate the stack size for the function if we're optimizing.  */
   self_stack_size = optimize ? estimated_stack_frame_size (node) : 0;
   inline_summary (node)->estimated_self_stack_size = self_stack_size;
@@ -247,17 +347,7 @@ compute_inline_parameters (struct cgraph_node *node)
       node->local.can_change_signature = !e;
     }
   estimate_function_body_sizes (node);
-  /* Compute size of call statements.  We have to do this for callers here,
-     those sizes need to be present for edges _to_ us as early as
-     we are finished with early opts.  */
-  for (e = node->callers; e; e = e->next_caller)
-    if (e->call_stmt)
-      {
-       e->call_stmt_size
-         = estimate_num_insns (e->call_stmt, &eni_size_weights);
-       e->call_stmt_time
-         = estimate_num_insns (e->call_stmt, &eni_time_weights);
-      }
+
   /* Inlining characteristics are maintained by the cgraph_mark_inline.  */
   node->global.time = inline_summary (node)->self_time;
   node->global.size = inline_summary (node)->self_size;
@@ -300,12 +390,8 @@ static inline int
 estimate_edge_time (struct cgraph_edge *edge)
 {
   int call_stmt_time;
-  /* ???  We throw away cgraph edges all the time so the information
-     we store in edges doesn't persist for early inlining.  Ugh.  */
-  if (!edge->call_stmt)
-    call_stmt_time = edge->call_stmt_time;
-  else
-    call_stmt_time = estimate_num_insns (edge->call_stmt, &eni_time_weights);
+  call_stmt_time = edge->call_stmt_time;
+  gcc_checking_assert (call_stmt_time);
   return (((gcov_type)edge->callee->global.time
           - inline_summary (edge->callee)->time_inlining_benefit
           - call_stmt_time) * edge->frequency
@@ -333,7 +419,7 @@ estimate_time_after_inlining (struct cgraph_node *node,
 
 int
 estimate_size_after_inlining (struct cgraph_node *node,
-                                    struct cgraph_edge *edge)
+                             struct cgraph_edge *edge)
 {
   int size = node->global.size + estimate_edge_growth (edge);
   gcc_assert (size >= 0);
@@ -379,8 +465,10 @@ estimate_growth (struct cgraph_node *node)
   return growth;
 }
 
+
 /* This function performs intraprocedural analysis in NODE that is required to
    inline indirect calls.  */
+
 static void
 inline_indirect_intraprocedural_analysis (struct cgraph_node *node)
 {
@@ -437,8 +525,6 @@ inline_generate_summary (void)
   for (node = cgraph_nodes; node; node = node->next)
     if (node->analyzed)
       inline_analyze_function (node);
-
-  return;
 }
 
 
@@ -449,6 +535,57 @@ inline_generate_summary (void)
 void
 inline_read_summary (void)
 {
+  struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
+  struct lto_file_decl_data *file_data;
+  unsigned int j = 0;
+
+  inline_summary_alloc ();
+
+  while ((file_data = file_data_vec[j++]))
+    {
+      size_t len;
+      const char *data = lto_get_section_data (file_data, LTO_section_inline_summary, NULL, &len);
+
+      struct lto_input_block *ib
+       = lto_create_simple_input_block (file_data,
+                                        LTO_section_inline_summary,
+                                        &data, &len);
+      if (ib)
+       {
+         unsigned int i;
+         unsigned int f_count = lto_input_uleb128 (ib);
+
+         for (i = 0; i < f_count; i++)
+           {
+             unsigned int index;
+             struct cgraph_node *node;
+             struct inline_summary *info;
+             lto_cgraph_encoder_t encoder;
+
+             index = lto_input_uleb128 (ib);
+             encoder = file_data->cgraph_node_encoder;
+             node = lto_cgraph_encoder_deref (encoder, index);
+             info = inline_summary (node);
+
+             node->global.estimated_stack_size
+               = info->estimated_self_stack_size = lto_input_uleb128 (ib);
+             node->global.time = info->self_time = lto_input_uleb128 (ib);
+             info->time_inlining_benefit = lto_input_uleb128 (ib);
+             node->global.size = info->self_size = lto_input_uleb128 (ib);
+             info->size_inlining_benefit = lto_input_uleb128 (ib);
+             node->global.estimated_growth = INT_MIN;
+           }
+
+         lto_destroy_simple_input_block (file_data,
+                                         LTO_section_inline_summary,
+                                         ib, data, len);
+       }
+      else
+       /* Fatal error here.  We do not want to support compiling ltrans units with
+          different version of compiler or different flags than the WPA unit, so
+          this should never happen.  */
+       fatal_error ("ipa inline summary is missing in input file");
+    }
   if (flag_indirect_inlining)
     {
       ipa_register_cgraph_hooks ();
@@ -468,14 +605,58 @@ void
 inline_write_summary (cgraph_node_set set,
                      varpool_node_set vset ATTRIBUTE_UNUSED)
 {
+  struct cgraph_node *node;
+  struct lto_simple_output_block *ob
+    = lto_create_simple_output_block (LTO_section_inline_summary);
+  lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder;
+  unsigned int count = 0;
+  int i;
+
+  for (i = 0; i < lto_cgraph_encoder_size (encoder); i++)
+    if (lto_cgraph_encoder_deref (encoder, i)->analyzed)
+      count++;
+  lto_output_uleb128_stream (ob->main_stream, count);
+
+  for (i = 0; i < lto_cgraph_encoder_size (encoder); i++)
+    {
+      node = lto_cgraph_encoder_deref (encoder, i);
+      if (node->analyzed)
+       {
+         struct inline_summary *info = inline_summary (node);
+         lto_output_uleb128_stream (ob->main_stream,
+                                    lto_cgraph_encoder_encode (encoder, node));
+         lto_output_sleb128_stream (ob->main_stream,
+                                    info->estimated_self_stack_size);
+         lto_output_sleb128_stream (ob->main_stream,
+                                    info->self_size);
+         lto_output_sleb128_stream (ob->main_stream,
+                                    info->size_inlining_benefit);
+         lto_output_sleb128_stream (ob->main_stream,
+                                    info->self_time);
+         lto_output_sleb128_stream (ob->main_stream,
+                                    info->time_inlining_benefit);
+       }
+    }
+  lto_destroy_simple_output_block (ob);
+
   if (flag_indirect_inlining && !flag_ipa_cp)
     ipa_prop_write_jump_functions (set);
 }
 
+
 /* Release inline summary.  */
 
 void
 inline_free_summary (void)
 {
-  cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
+  if (function_insertion_hook_holder)
+    cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
+  function_insertion_hook_holder = NULL;
+  if (node_removal_hook_holder)
+    cgraph_remove_node_removal_hook (node_removal_hook_holder);
+  node_removal_hook_holder = NULL;
+  if (node_duplication_hook_holder)
+    cgraph_remove_node_duplication_hook (node_duplication_hook_holder);
+  node_duplication_hook_holder = NULL;
+  VEC_free (inline_summary_t, heap, inline_summary_vec);
 }
index 36bc1c2dbd65cffa16fdeade95d7003708d28e0b..1dbb3248fabcd89ea421f325b9018546396c9cca 100644 (file)
@@ -1301,6 +1301,9 @@ cgraph_decide_inlining (void)
              max_benefit = benefit;
          }
       }
+
+  if (dump_file)
+    dump_inline_summaries (dump_file);
   gcc_assert (in_lto_p
              || !max_count
              || (profile_info && flag_branch_probabilities));
@@ -1415,7 +1418,9 @@ cgraph_decide_inlining (void)
             ncalls_inlined, nfunctions_inlined, initial_size,
             overall_size);
   free (order);
-  inline_free_summary ();
+  /* In WPA we use inline summaries for partitioning process.  */
+  if (!flag_wpa)
+    inline_free_summary ();
   return 0;
 }
 
@@ -1558,8 +1563,7 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node)
       /* When the function body would grow and inlining the function
         won't eliminate the need for offline copy of the function,
         don't inline.  */
-      if (estimate_edge_growth (e) > allowed_growth
-         && estimate_growth (e->callee) > allowed_growth)
+      if (estimate_edge_growth (e) > allowed_growth)
        {
          if (dump_file)
            fprintf (dump_file,
@@ -1601,6 +1605,7 @@ static unsigned int
 cgraph_early_inlining (void)
 {
   struct cgraph_node *node = cgraph_get_node (current_function_decl);
+  struct cgraph_edge *edge;
   unsigned int todo = 0;
   int iterations = 0;
   bool inlined = false;
@@ -1652,6 +1657,19 @@ cgraph_early_inlining (void)
     {
       timevar_push (TV_INTEGRATION);
       todo |= optimize_inline_calls (current_function_decl);
+
+      /* Technically we ought to recompute inline parameters so the new iteration of
+        early inliner works as expected.  We however have values approximately right
+        and thus we only need to update edge info that might be cleared out for
+        newly discovered edges.  */
+      for (edge = node->callees; edge; edge = edge->next_callee)
+       {
+         edge->call_stmt_size
+           = estimate_num_insns (edge->call_stmt, &eni_size_weights);
+         edge->call_stmt_time
+           = estimate_num_insns (edge->call_stmt, &eni_time_weights);
+       }
+
       timevar_pop (TV_INTEGRATION);
     }
 
index d76a492a1d2130246f292ef44848105809219803..e9a7db21043f3b5cedba4d0e724f0488c2c6a57f 100644 (file)
@@ -19,6 +19,30 @@ 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/>.  */
 
+/* Function inlining information.  */
+
+struct inline_summary
+{
+  /* Estimated stack frame consumption by the function.  */
+  HOST_WIDE_INT estimated_self_stack_size;
+
+  /* Size of the function body.  */
+  int self_size;
+  /* How many instructions are likely going to disappear after inlining.  */
+  int size_inlining_benefit;
+  /* Estimated time spent executing the function body.  */
+  int self_time;
+  /* How much time is going to be saved by inlining.  */
+  int time_inlining_benefit;
+};
+
+typedef struct inline_summary inline_summary_t;
+DEF_VEC_O(inline_summary_t);
+DEF_VEC_ALLOC_O(inline_summary_t,heap);
+extern VEC(inline_summary_t,heap) *inline_summary_vec;
+
+void debug_inline_summary (struct cgraph_node *);
+void dump_inline_summaries (FILE *f);
 void inline_generate_summary (void);
 void inline_read_summary (void);
 void inline_write_summary (cgraph_node_set, varpool_node_set);
@@ -30,7 +54,7 @@ int estimate_growth (struct cgraph_node *);
 static inline struct inline_summary *
 inline_summary (struct cgraph_node *node)
 {
-  return &node->local.inline_summary;
+  return VEC_index (inline_summary_t, inline_summary_vec, node->uid);
 }
 
 /* Estimate the growth of the caller when inlining EDGE.  */
@@ -39,12 +63,8 @@ static inline int
 estimate_edge_growth (struct cgraph_edge *edge)
 {
   int call_stmt_size;
-  /* ???  We throw away cgraph edges all the time so the information
-     we store in edges doesn't persist for early inlining.  Ugh.  */
-  if (!edge->call_stmt)
-    call_stmt_size = edge->call_stmt_size;
-  else
-    call_stmt_size = estimate_num_insns (edge->call_stmt, &eni_size_weights);
+  call_stmt_size = edge->call_stmt_size;
+  gcc_checking_assert (call_stmt_size);
   return (edge->callee->global.size
          - inline_summary (edge->callee)->size_inlining_benefit
          - call_stmt_size);
index cc5e8ee11c29826484729bfbbda1c745fb65fcbe..9a50ce2c007461bb5b24e479e6c6a3c232ecb9a9 100644 (file)
@@ -1998,7 +1998,7 @@ ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
 
 static void
 ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
-                          __attribute__((unused)) void *data)
+                          ATTRIBUTE_UNUSED void *data)
 {
   struct ipa_node_params *old_info, *new_info;
   int param_count, i;
index 24f686e8207ff6b20c060a158753d9ccae49648a..84a3d97e8a9b609bde904723eb92ecb1d7024e1e 100644 (file)
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -517,6 +517,8 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
              }
          }
       }
+  if (file)
+    fprintf (file, "\n");
 
 #ifdef ENABLE_CHECKING
   verify_cgraph ();
index 63680d3cb75f7071a10cf551117b8856e78c6aec..c1544577dd5a28171a770dcfe4ab42c4ec071ab6 100644 (file)
@@ -465,16 +465,6 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
 
   if (tag == LTO_cgraph_analyzed_node)
     {
-      lto_output_sleb128_stream (ob->main_stream,
-                                node->local.inline_summary.estimated_self_stack_size);
-      lto_output_sleb128_stream (ob->main_stream,
-                                node->local.inline_summary.self_size);
-      lto_output_sleb128_stream (ob->main_stream,
-                                node->local.inline_summary.size_inlining_benefit);
-      lto_output_sleb128_stream (ob->main_stream,
-                                node->local.inline_summary.self_time);
-      lto_output_sleb128_stream (ob->main_stream,
-                                node->local.inline_summary.time_inlining_benefit);
       if (node->global.inlined_to)
        {
          ref = lto_cgraph_encoder_lookup (encoder, node->global.inlined_to);
@@ -930,23 +920,9 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
                      struct cgraph_node *node,
                      enum LTO_cgraph_tags tag,
                      struct bitpack_d *bp,
-                     unsigned int stack_size,
-                     unsigned int self_time,
-                     unsigned int time_inlining_benefit,
-                     unsigned int self_size,
-                     unsigned int size_inlining_benefit,
                      enum ld_plugin_symbol_resolution resolution)
 {
   node->aux = (void *) tag;
-  node->local.inline_summary.estimated_self_stack_size = stack_size;
-  node->local.inline_summary.self_time = self_time;
-  node->local.inline_summary.time_inlining_benefit = time_inlining_benefit;
-  node->local.inline_summary.self_size = self_size;
-  node->local.inline_summary.size_inlining_benefit = size_inlining_benefit;
-  node->global.time = self_time;
-  node->global.size = self_size;
-  node->global.estimated_stack_size = stack_size;
-  node->global.estimated_growth = INT_MIN;
   node->local.lto_file_data = file_data;
 
   node->local.local = bp_unpack_value (bp, 1);
@@ -1023,13 +999,8 @@ input_node (struct lto_file_decl_data *file_data,
   tree fn_decl;
   struct cgraph_node *node;
   struct bitpack_d bp;
-  int stack_size = 0;
   unsigned decl_index;
   int ref = LCC_NOT_FOUND, ref2 = LCC_NOT_FOUND;
-  int self_time = 0;
-  int self_size = 0;
-  int time_inlining_benefit = 0;
-  int size_inlining_benefit = 0;
   unsigned long same_body_count = 0;
   int clone_ref;
   enum ld_plugin_symbol_resolution resolution;
@@ -1051,15 +1022,7 @@ input_node (struct lto_file_decl_data *file_data,
   node->count_materialization_scale = lto_input_sleb128 (ib);
 
   if (tag == LTO_cgraph_analyzed_node)
-    {
-      stack_size = lto_input_sleb128 (ib);
-      self_size = lto_input_sleb128 (ib);
-      size_inlining_benefit = lto_input_sleb128 (ib);
-      self_time = lto_input_sleb128 (ib);
-      time_inlining_benefit = lto_input_sleb128 (ib);
-
-      ref = lto_input_sleb128 (ib);
-    }
+    ref = lto_input_sleb128 (ib);
 
   ref2 = lto_input_sleb128 (ib);
 
@@ -1073,9 +1036,7 @@ input_node (struct lto_file_decl_data *file_data,
 
   bp = lto_input_bitpack (ib);
   resolution = (enum ld_plugin_symbol_resolution)lto_input_uleb128 (ib);
-  input_overwrite_node (file_data, node, tag, &bp, stack_size, self_time,
-                       time_inlining_benefit, self_size,
-                       size_inlining_benefit, resolution);
+  input_overwrite_node (file_data, node, tag, &bp, resolution);
 
   /* Store a reference for now, and fix up later to be a pointer.  */
   node->global.inlined_to = (cgraph_node_ptr) (intptr_t) ref;
index bfa9c37b68ba0c8d795bd0f47e24333f9c5dcf51..e7928c4b971fc90c60993b23a543c528569d3bf8 100644 (file)
@@ -58,7 +58,8 @@ const char *lto_section_name[LTO_N_SECTION_TYPES] =
   "reference",
   "symtab",
   "opts",
-  "cgraphopt"
+  "cgraphopt",
+  "inline"
 };
 
 unsigned char
index 43b8fcb77a632de54f1634de3adf072310d81bbd..5d1f15a783ee3dc4fd21a3553d73fa83c436902a 100644 (file)
@@ -264,6 +264,7 @@ enum lto_section_type
   LTO_section_symtab,
   LTO_section_opts,
   LTO_section_cgraph_opt_sum,
+  LTO_section_inline_summary,
   LTO_N_SECTION_TYPES          /* Must be last.  */
 };
 
index bc72f2f41beb2199842c971412c004f629265add..45dd300dedddd27980078cef8256df01257f050b 100644 (file)
@@ -1,3 +1,10 @@
+2011-04-14  Jan Hubicka  <jh@suse.cz>
+
+       * lto.c: Include ipa-inline.h
+       (add_cgraph_node_to_partition, undo_partition): Use inline_summary accessor.
+       (ipa_node_duplication_hook): Fix declaration.
+       * Make-lang.in (lto.o): Update dependencies.
+
 2011-04-12  Nathan Froyd  <froydnj@codesourcery.com>
 
        * lto-tree.h (union lang_tree_node): Check for TS_COMMON before
index 1c8618ded276d64aaf67dec44354a04df0596a98..5287c12708885c44e087f0d072c7f49cff3ea46e 100644 (file)
@@ -85,7 +85,8 @@ lto/lto.o: lto/lto.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(OPTS_H) \
        $(CGRAPH_H) $(GGC_H) tree-ssa-operands.h $(TREE_PASS_H) \
        langhooks.h $(VEC_H) $(BITMAP_H) pointer-set.h $(IPA_PROP_H) \
        $(COMMON_H) debug.h $(TIMEVAR_H) $(GIMPLE_H) $(LTO_H) $(LTO_TREE_H) \
-       $(LTO_TAGS_H) $(LTO_STREAMER_H) $(SPLAY_TREE_H) gt-lto-lto.h $(PARAMS_H)
+       $(LTO_TAGS_H) $(LTO_STREAMER_H) $(SPLAY_TREE_H) gt-lto-lto.h $(PARAMS_H) \
+       ipa-inline.h
 lto/lto-object.o: lto/lto-object.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
        $(DIAGNOSTIC_CORE_H) $(LTO_H) $(TM_H) $(LTO_STREAMER_H) \
        ../include/simple-object.h
index eebc50f1553cacef6518350ca2032635e5240f0e..9103af45202ab3fb883fbb402d1aaa5f34a2aa20 100644 (file)
@@ -44,6 +44,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "lto-streamer.h"
 #include "splay-tree.h"
 #include "params.h"
+#include "ipa-inline.h"
 
 static GTY(()) tree first_personality_decl;
 
@@ -750,7 +751,7 @@ add_cgraph_node_to_partition (ltrans_partition part, struct cgraph_node *node)
 {
   struct cgraph_edge *e;
 
-  part->insns += node->local.inline_summary.self_size;
+  part->insns += inline_summary (node)->self_size;
 
   if (node->aux)
     {
@@ -811,7 +812,7 @@ undo_partition (ltrans_partition partition, unsigned int n_cgraph_nodes,
       struct cgraph_node *node = VEC_index (cgraph_node_ptr,
                                            partition->cgraph_set->nodes,
                                            n_cgraph_nodes);
-      partition->insns -= node->local.inline_summary.self_size;
+      partition->insns -= inline_summary (node)->self_size;
       cgraph_node_set_remove (partition->cgraph_set, node);
       node->aux = (void *)((size_t)node->aux - 1);
     }