OSDN Git Service

PR tree-optimization/48622
[pf3gnuchains/gcc-fork.git] / gcc / ipa-inline-analysis.c
1 /* Inlining decision heuristics.
2    Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011
3    Free Software Foundation, Inc.
4    Contributed by Jan Hubicka
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21
22 /* Analysis used by the inliner and other passes limiting code size growth.
23
24    We estimate for each function
25      - function body size
26      - average function execution time
27      - inlining size benefit (that is how much of function body size
28        and its call sequence is expected to disappear by inlining)
29      - inlining time benefit
30      - function frame size
31    For each call
32      - call statement size and time
33
34    inlinie_summary datastructures store above information locally (i.e.
35    parameters of the function itself) and globally (i.e. parameters of
36    the function created by applying all the inline decisions already
37    present in the callgraph).
38
39    We also provide accestor to the inline_summary datastructure and
40    basic logic updating the parameters when inlining is performed. 
41
42    Finally pass_inline_parameters is exported.  This is used to drive
43    computation of function parameters used by the early inliner. IPA
44    inlined performs analysis via its analyze_function method. */
45
46 #include "config.h"
47 #include "system.h"
48 #include "coretypes.h"
49 #include "tm.h"
50 #include "tree.h"
51 #include "tree-inline.h"
52 #include "langhooks.h"
53 #include "flags.h"
54 #include "cgraph.h"
55 #include "diagnostic.h"
56 #include "gimple-pretty-print.h"
57 #include "timevar.h"
58 #include "params.h"
59 #include "tree-pass.h"
60 #include "coverage.h"
61 #include "ggc.h"
62 #include "tree-flow.h"
63 #include "ipa-prop.h"
64 #include "lto-streamer.h"
65 #include "ipa-inline.h"
66
67 #define MAX_TIME 1000000000
68
69 /* Holders of ipa cgraph hooks: */
70 static struct cgraph_node_hook_list *function_insertion_hook_holder;
71 static struct cgraph_node_hook_list *node_removal_hook_holder;
72 static struct cgraph_2node_hook_list *node_duplication_hook_holder;
73 static void inline_node_removal_hook (struct cgraph_node *, void *);
74 static void inline_node_duplication_hook (struct cgraph_node *,
75                                           struct cgraph_node *, void *);
76
77 /* VECtor holding inline summaries.  */
78 VEC(inline_summary_t,heap) *inline_summary_vec;
79
80 /* Allocate the inline summary vector or resize it to cover all cgraph nodes. */
81
82 static void
83 inline_summary_alloc (void)
84 {
85   if (!node_removal_hook_holder)
86     node_removal_hook_holder =
87       cgraph_add_node_removal_hook (&inline_node_removal_hook, NULL);
88   if (!node_duplication_hook_holder)
89     node_duplication_hook_holder =
90       cgraph_add_node_duplication_hook (&inline_node_duplication_hook, NULL);
91
92   if (VEC_length (inline_summary_t, inline_summary_vec)
93       <= (unsigned) cgraph_max_uid)
94     VEC_safe_grow_cleared (inline_summary_t, heap,
95                            inline_summary_vec, cgraph_max_uid + 1);
96 }
97
98 /* Hook that is called by cgraph.c when a node is removed.  */
99
100 static void
101 inline_node_removal_hook (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
102 {
103   struct inline_summary *info;
104   if (VEC_length (inline_summary_t, inline_summary_vec)
105       <= (unsigned)node->uid)
106     return;
107   info = inline_summary (node);
108   info->estimated_growth = INT_MIN;
109   memset (info, 0, sizeof (inline_summary_t));
110 }
111
112 /* Hook that is called by cgraph.c when a node is duplicated.  */
113
114 static void
115 inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
116                               ATTRIBUTE_UNUSED void *data)
117 {
118   struct inline_summary *info;
119   inline_summary_alloc ();
120   info = inline_summary (dst);
121   memcpy (info, inline_summary (src),
122           sizeof (struct inline_summary));
123   info->estimated_growth = INT_MIN;
124 }
125
126 static void
127 dump_inline_summary (FILE *f, struct cgraph_node *node)
128 {
129   if (node->analyzed)
130     {
131       struct inline_summary *s = inline_summary (node);
132       fprintf (f, "Inline summary for %s/%i", cgraph_node_name (node),
133                node->uid);
134       if (s->disregard_inline_limits)
135         fprintf (f, " always_inline");
136       if (s->inlinable)
137         fprintf (f, " inlinable");
138       if (s->versionable)
139         fprintf (f, " versionable");
140       fprintf (f, "\n  self time:       %i, benefit: %i\n",
141                s->self_time, s->time_inlining_benefit);
142       fprintf (f, "  global time:     %i\n", s->time);
143       fprintf (f, "  self size:       %i, benefit: %i\n",
144                s->self_size, s->size_inlining_benefit);
145       fprintf (f, "  global size:     %i", s->size);
146       fprintf (f, "  self stack:      %i\n",
147                (int)s->estimated_self_stack_size);
148       fprintf (f, "  global stack:    %i\n\n",
149                (int)s->estimated_stack_size);
150     }
151 }
152
153 void
154 debug_inline_summary (struct cgraph_node *node)
155 {
156   dump_inline_summary (stderr, node);
157 }
158
159 void
160 dump_inline_summaries (FILE *f)
161 {
162   struct cgraph_node *node;
163
164   for (node = cgraph_nodes; node; node = node->next)
165     if (node->analyzed)
166       dump_inline_summary (f, node);
167 }
168
169 /* Give initial reasons why inlining would fail on EDGE.  This gets either
170    nullified or usually overwritten by more precise reasons later.  */
171
172 void
173 initialize_inline_failed (struct cgraph_edge *e)
174 {
175   struct cgraph_node *callee = e->callee;
176
177   if (e->indirect_unknown_callee)
178     e->inline_failed = CIF_INDIRECT_UNKNOWN_CALL;
179   else if (!callee->analyzed)
180     e->inline_failed = CIF_BODY_NOT_AVAILABLE;
181   else if (callee->local.redefined_extern_inline)
182     e->inline_failed = CIF_REDEFINED_EXTERN_INLINE;
183   else if (e->call_stmt && gimple_call_cannot_inline_p (e->call_stmt))
184     e->inline_failed = CIF_MISMATCHED_ARGUMENTS;
185   else
186     e->inline_failed = CIF_FUNCTION_NOT_CONSIDERED;
187 }
188
189 /* See if statement might disappear after inlining.
190    0 - means not eliminated
191    1 - half of statements goes away
192    2 - for sure it is eliminated.
193    We are not terribly sophisticated, basically looking for simple abstraction
194    penalty wrappers.  */
195
196 static int
197 eliminated_by_inlining_prob (gimple stmt)
198 {
199   enum gimple_code code = gimple_code (stmt);
200   switch (code)
201     {
202       case GIMPLE_RETURN:
203         return 2;
204       case GIMPLE_ASSIGN:
205         if (gimple_num_ops (stmt) != 2)
206           return 0;
207
208         /* Casts of parameters, loads from parameters passed by reference
209            and stores to return value or parameters are often free after
210            inlining dua to SRA and further combining.
211            Assume that half of statements goes away.  */
212         if (gimple_assign_rhs_code (stmt) == CONVERT_EXPR
213             || gimple_assign_rhs_code (stmt) == NOP_EXPR
214             || gimple_assign_rhs_code (stmt) == VIEW_CONVERT_EXPR
215             || gimple_assign_rhs_class (stmt) == GIMPLE_SINGLE_RHS)
216           {
217             tree rhs = gimple_assign_rhs1 (stmt);
218             tree lhs = gimple_assign_lhs (stmt);
219             tree inner_rhs = rhs;
220             tree inner_lhs = lhs;
221             bool rhs_free = false;
222             bool lhs_free = false;
223
224             while (handled_component_p (inner_lhs)
225                    || TREE_CODE (inner_lhs) == MEM_REF)
226               inner_lhs = TREE_OPERAND (inner_lhs, 0);
227             while (handled_component_p (inner_rhs)
228                    || TREE_CODE (inner_rhs) == ADDR_EXPR
229                    || TREE_CODE (inner_rhs) == MEM_REF)
230               inner_rhs = TREE_OPERAND (inner_rhs, 0);
231
232
233             if (TREE_CODE (inner_rhs) == PARM_DECL
234                 || (TREE_CODE (inner_rhs) == SSA_NAME
235                     && SSA_NAME_IS_DEFAULT_DEF (inner_rhs)
236                     && TREE_CODE (SSA_NAME_VAR (inner_rhs)) == PARM_DECL))
237               rhs_free = true;
238             if (rhs_free && is_gimple_reg (lhs))
239               lhs_free = true;
240             if (((TREE_CODE (inner_lhs) == PARM_DECL
241                   || (TREE_CODE (inner_lhs) == SSA_NAME
242                       && SSA_NAME_IS_DEFAULT_DEF (inner_lhs)
243                       && TREE_CODE (SSA_NAME_VAR (inner_lhs)) == PARM_DECL))
244                  && inner_lhs != lhs)
245                 || TREE_CODE (inner_lhs) == RESULT_DECL
246                 || (TREE_CODE (inner_lhs) == SSA_NAME
247                     && TREE_CODE (SSA_NAME_VAR (inner_lhs)) == RESULT_DECL))
248               lhs_free = true;
249             if (lhs_free
250                 && (is_gimple_reg (rhs) || is_gimple_min_invariant (rhs)))
251               rhs_free = true;
252             if (lhs_free && rhs_free)
253               return 1;
254           }
255         return 0;
256       default:
257         return 0;
258     }
259 }
260
261
262 /* Compute function body size parameters for NODE.  */
263
264 static void
265 estimate_function_body_sizes (struct cgraph_node *node)
266 {
267   gcov_type time = 0;
268   gcov_type time_inlining_benefit = 0;
269   /* Estimate static overhead for function prologue/epilogue and alignment. */
270   int size = 2;
271   /* Benefits are scaled by probability of elimination that is in range
272      <0,2>.  */
273   int size_inlining_benefit = 2 * 2;
274   basic_block bb;
275   gimple_stmt_iterator bsi;
276   struct function *my_function = DECL_STRUCT_FUNCTION (node->decl);
277   int freq;
278
279   if (dump_file)
280     fprintf (dump_file, "Analyzing function body size: %s\n",
281              cgraph_node_name (node));
282
283   gcc_assert (my_function && my_function->cfg);
284   FOR_EACH_BB_FN (bb, my_function)
285     {
286       freq = compute_call_stmt_bb_frequency (node->decl, bb);
287       for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
288         {
289           gimple stmt = gsi_stmt (bsi);
290           int this_size = estimate_num_insns (stmt, &eni_size_weights);
291           int this_time = estimate_num_insns (stmt, &eni_time_weights);
292           int prob;
293
294           if (dump_file && (dump_flags & TDF_DETAILS))
295             {
296               fprintf (dump_file, "  freq:%6i size:%3i time:%3i ",
297                        freq, this_size, this_time);
298               print_gimple_stmt (dump_file, stmt, 0, 0);
299             }
300
301           if (is_gimple_call (stmt))
302             {
303               struct cgraph_edge *edge = cgraph_edge (node, stmt);
304               edge->call_stmt_size = this_size;
305               edge->call_stmt_time = this_time;
306             }
307
308           this_time *= freq;
309           time += this_time;
310           size += this_size;
311
312           prob = eliminated_by_inlining_prob (stmt);
313           if (prob == 1 && dump_file && (dump_flags & TDF_DETAILS))
314             fprintf (dump_file, "    50%% will be eliminated by inlining\n");
315           if (prob == 2 && dump_file && (dump_flags & TDF_DETAILS))
316             fprintf (dump_file, "    will eliminated by inlining\n");
317
318           size_inlining_benefit += this_size * prob;
319           time_inlining_benefit += this_time * prob;
320
321           gcc_assert (time >= 0);
322           gcc_assert (size >= 0);
323         }
324     }
325   time = (time + CGRAPH_FREQ_BASE / 2) / CGRAPH_FREQ_BASE;
326   time_inlining_benefit = ((time_inlining_benefit + CGRAPH_FREQ_BASE)
327                            / (CGRAPH_FREQ_BASE * 2));
328   size_inlining_benefit = (size_inlining_benefit + 1) / 2;
329   if (time_inlining_benefit > MAX_TIME)
330     time_inlining_benefit = MAX_TIME;
331   if (time > MAX_TIME)
332     time = MAX_TIME;
333   if (dump_file)
334     fprintf (dump_file, "Overall function body time: %i-%i size: %i-%i\n",
335              (int)time, (int)time_inlining_benefit,
336              size, size_inlining_benefit);
337   inline_summary (node)->self_time = time;
338   inline_summary (node)->self_size = size;
339   inline_summary (node)->time_inlining_benefit = time_inlining_benefit;
340   inline_summary (node)->size_inlining_benefit = size_inlining_benefit;
341 }
342
343
344 /* Compute parameters of functions used by inliner.  */
345
346 void
347 compute_inline_parameters (struct cgraph_node *node)
348 {
349   HOST_WIDE_INT self_stack_size;
350   struct cgraph_edge *e;
351   struct inline_summary *info;
352
353   gcc_assert (!node->global.inlined_to);
354
355   inline_summary_alloc ();
356
357   info = inline_summary (node);
358
359   /* Estimate the stack size for the function if we're optimizing.  */
360   self_stack_size = optimize ? estimated_stack_frame_size (node) : 0;
361   info->estimated_self_stack_size = self_stack_size;
362   info->estimated_stack_size = self_stack_size;
363   info->stack_frame_offset = 0;
364
365   /* Can this function be inlined at all?  */
366   info->inlinable = tree_inlinable_function_p (node->decl);
367   if (!info->inlinable)
368     info->disregard_inline_limits = 0;
369
370   /* Inlinable functions always can change signature.  */
371   if (info->inlinable)
372     node->local.can_change_signature = true;
373   else
374     {
375       /* Functions calling builtin_apply can not change signature.  */
376       for (e = node->callees; e; e = e->next_callee)
377         if (DECL_BUILT_IN (e->callee->decl)
378             && DECL_BUILT_IN_CLASS (e->callee->decl) == BUILT_IN_NORMAL
379             && DECL_FUNCTION_CODE (e->callee->decl) == BUILT_IN_APPLY_ARGS)
380           break;
381       node->local.can_change_signature = !e;
382     }
383   estimate_function_body_sizes (node);
384
385   /* Inlining characteristics are maintained by the cgraph_mark_inline.  */
386   info->time = info->self_time;
387   info->size = info->self_size;
388   info->estimated_growth = INT_MIN;
389   info->stack_frame_offset = 0;
390   info->estimated_stack_size = info->estimated_self_stack_size;
391   info->disregard_inline_limits
392     = DECL_DISREGARD_INLINE_LIMITS (node->decl);
393 }
394
395
396 /* Compute parameters of functions used by inliner using
397    current_function_decl.  */
398
399 static unsigned int
400 compute_inline_parameters_for_current (void)
401 {
402   compute_inline_parameters (cgraph_get_node (current_function_decl));
403   return 0;
404 }
405
406 struct gimple_opt_pass pass_inline_parameters =
407 {
408  {
409   GIMPLE_PASS,
410   "inline_param",                       /* name */
411   NULL,                                 /* gate */
412   compute_inline_parameters_for_current,/* execute */
413   NULL,                                 /* sub */
414   NULL,                                 /* next */
415   0,                                    /* static_pass_number */
416   TV_INLINE_HEURISTICS,                 /* tv_id */
417   0,                                    /* properties_required */
418   0,                                    /* properties_provided */
419   0,                                    /* properties_destroyed */
420   0,                                    /* todo_flags_start */
421   0                                     /* todo_flags_finish */
422  }
423 };
424
425
426 /* Estimate the time cost for the caller when inlining EDGE.  */
427
428 static inline int
429 estimate_edge_time (struct cgraph_edge *edge)
430 {
431   int call_stmt_time;
432   struct inline_summary *info = inline_summary (edge->callee);
433
434   call_stmt_time = edge->call_stmt_time;
435   gcc_checking_assert (call_stmt_time);
436   return (((gcov_type)info->time
437            - info->time_inlining_benefit
438            - call_stmt_time) * edge->frequency
439           + CGRAPH_FREQ_BASE / 2) / CGRAPH_FREQ_BASE;
440 }
441
442
443 /* Estimate self time of the function NODE after inlining EDGE.  */
444
445 int
446 estimate_time_after_inlining (struct cgraph_node *node,
447                               struct cgraph_edge *edge)
448 {
449   gcov_type time = inline_summary (node)->time + estimate_edge_time (edge);
450   if (time < 0)
451     time = 0;
452   if (time > MAX_TIME)
453     time = MAX_TIME;
454   return time;
455 }
456
457
458 /* Estimate the size of NODE after inlining EDGE which should be an
459    edge to either NODE or a call inlined into NODE.  */
460
461 int
462 estimate_size_after_inlining (struct cgraph_node *node,
463                               struct cgraph_edge *edge)
464 {
465   int size = inline_summary (node)->size + estimate_edge_growth (edge);
466   gcc_assert (size >= 0);
467   return size;
468 }
469
470
471 /* Estimate the growth caused by inlining NODE into all callees.  */
472
473 int
474 estimate_growth (struct cgraph_node *node)
475 {
476   int growth = 0;
477   struct cgraph_edge *e;
478   bool self_recursive = false;
479   struct inline_summary *info = inline_summary (node);
480
481   if (info->estimated_growth != INT_MIN)
482     return info->estimated_growth;
483
484   for (e = node->callers; e; e = e->next_caller)
485     {
486       if (e->caller == node)
487         self_recursive = true;
488       if (e->inline_failed)
489         growth += estimate_edge_growth (e);
490     }
491
492   /* ??? Wrong for non-trivially self recursive functions or cases where
493      we decide to not inline for different reasons, but it is not big deal
494      as in that case we will keep the body around, but we will also avoid
495      some inlining.  */
496   if (cgraph_will_be_removed_from_program_if_no_direct_calls (node)
497       && !DECL_EXTERNAL (node->decl) && !self_recursive)
498     growth -= info->size;
499   /* COMDAT functions are very often not shared across multiple units since they
500      come from various template instantiations.  Take this into account.  */
501   else  if (DECL_COMDAT (node->decl) && !self_recursive
502             && cgraph_can_remove_if_no_direct_calls_p (node))
503     growth -= (info->size
504                * (100 - PARAM_VALUE (PARAM_COMDAT_SHARING_PROBABILITY)) + 50) / 100;
505
506   info->estimated_growth = growth;
507   return growth;
508 }
509
510
511 /* This function performs intraprocedural analysis in NODE that is required to
512    inline indirect calls.  */
513
514 static void
515 inline_indirect_intraprocedural_analysis (struct cgraph_node *node)
516 {
517   ipa_analyze_node (node);
518   if (dump_file && (dump_flags & TDF_DETAILS))
519     {
520       ipa_print_node_params (dump_file, node);
521       ipa_print_node_jump_functions (dump_file, node);
522     }
523 }
524
525
526 /* Note function body size.  */
527
528 static void
529 inline_analyze_function (struct cgraph_node *node)
530 {
531   push_cfun (DECL_STRUCT_FUNCTION (node->decl));
532   current_function_decl = node->decl;
533
534   compute_inline_parameters (node);
535   /* FIXME: We should remove the optimize check after we ensure we never run
536      IPA passes when not optimizing.  */
537   if (flag_indirect_inlining && optimize)
538     inline_indirect_intraprocedural_analysis (node);
539
540   current_function_decl = NULL;
541   pop_cfun ();
542 }
543
544
545 /* Called when new function is inserted to callgraph late.  */
546
547 static void
548 add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
549 {
550   inline_analyze_function (node);
551 }
552
553
554 /* Note function body size.  */
555
556 void
557 inline_generate_summary (void)
558 {
559   struct cgraph_node *node;
560
561   function_insertion_hook_holder =
562       cgraph_add_function_insertion_hook (&add_new_function, NULL);
563
564   if (flag_indirect_inlining)
565     ipa_register_cgraph_hooks ();
566
567   for (node = cgraph_nodes; node; node = node->next)
568     if (node->analyzed)
569       inline_analyze_function (node);
570 }
571
572
573 /* Read inline summary.  Jump functions are shared among ipa-cp
574    and inliner, so when ipa-cp is active, we don't need to write them
575    twice.  */
576
577 void
578 inline_read_summary (void)
579 {
580   struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
581   struct lto_file_decl_data *file_data;
582   unsigned int j = 0;
583
584   inline_summary_alloc ();
585
586   while ((file_data = file_data_vec[j++]))
587     {
588       size_t len;
589       const char *data = lto_get_section_data (file_data, LTO_section_inline_summary, NULL, &len);
590
591       struct lto_input_block *ib
592         = lto_create_simple_input_block (file_data,
593                                          LTO_section_inline_summary,
594                                          &data, &len);
595       if (ib)
596         {
597           unsigned int i;
598           unsigned int f_count = lto_input_uleb128 (ib);
599
600           for (i = 0; i < f_count; i++)
601             {
602               unsigned int index;
603               struct cgraph_node *node;
604               struct inline_summary *info;
605               lto_cgraph_encoder_t encoder;
606               struct bitpack_d bp;
607
608               index = lto_input_uleb128 (ib);
609               encoder = file_data->cgraph_node_encoder;
610               node = lto_cgraph_encoder_deref (encoder, index);
611               info = inline_summary (node);
612
613               info->estimated_stack_size
614                 = info->estimated_self_stack_size = lto_input_uleb128 (ib);
615               info->size = info->self_size = lto_input_uleb128 (ib);
616               info->size_inlining_benefit = lto_input_uleb128 (ib);
617               info->time = info->self_time = lto_input_uleb128 (ib);
618               info->time_inlining_benefit = lto_input_uleb128 (ib);
619               info->estimated_growth = INT_MIN;
620
621               bp = lto_input_bitpack (ib);
622               info->inlinable = bp_unpack_value (&bp, 1);
623               info->versionable = bp_unpack_value (&bp, 1);
624               info->disregard_inline_limits = bp_unpack_value (&bp, 1);
625             }
626
627           lto_destroy_simple_input_block (file_data,
628                                           LTO_section_inline_summary,
629                                           ib, data, len);
630         }
631       else
632         /* Fatal error here.  We do not want to support compiling ltrans units with
633            different version of compiler or different flags than the WPA unit, so
634            this should never happen.  */
635         fatal_error ("ipa inline summary is missing in input file");
636     }
637   if (flag_indirect_inlining)
638     {
639       ipa_register_cgraph_hooks ();
640       if (!flag_ipa_cp)
641         ipa_prop_read_jump_functions ();
642     }
643   function_insertion_hook_holder =
644       cgraph_add_function_insertion_hook (&add_new_function, NULL);
645 }
646
647
648 /* Write inline summary for node in SET.
649    Jump functions are shared among ipa-cp and inliner, so when ipa-cp is
650    active, we don't need to write them twice.  */
651
652 void
653 inline_write_summary (cgraph_node_set set,
654                       varpool_node_set vset ATTRIBUTE_UNUSED)
655 {
656   struct cgraph_node *node;
657   struct lto_simple_output_block *ob
658     = lto_create_simple_output_block (LTO_section_inline_summary);
659   lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder;
660   unsigned int count = 0;
661   int i;
662
663   for (i = 0; i < lto_cgraph_encoder_size (encoder); i++)
664     if (lto_cgraph_encoder_deref (encoder, i)->analyzed)
665       count++;
666   lto_output_uleb128_stream (ob->main_stream, count);
667
668   for (i = 0; i < lto_cgraph_encoder_size (encoder); i++)
669     {
670       node = lto_cgraph_encoder_deref (encoder, i);
671       if (node->analyzed)
672         {
673           struct inline_summary *info = inline_summary (node);
674           struct bitpack_d bp;
675
676           lto_output_uleb128_stream (ob->main_stream,
677                                      lto_cgraph_encoder_encode (encoder, node));
678           lto_output_sleb128_stream (ob->main_stream,
679                                      info->estimated_self_stack_size);
680           lto_output_sleb128_stream (ob->main_stream,
681                                      info->self_size);
682           lto_output_sleb128_stream (ob->main_stream,
683                                      info->size_inlining_benefit);
684           lto_output_sleb128_stream (ob->main_stream,
685                                      info->self_time);
686           lto_output_sleb128_stream (ob->main_stream,
687                                      info->time_inlining_benefit);
688           bp = bitpack_create (ob->main_stream);
689           bp_pack_value (&bp, info->inlinable, 1);
690           bp_pack_value (&bp, info->versionable, 1);
691           bp_pack_value (&bp, info->disregard_inline_limits, 1);
692           lto_output_bitpack (&bp);
693         }
694     }
695   lto_destroy_simple_output_block (ob);
696
697   if (flag_indirect_inlining && !flag_ipa_cp)
698     ipa_prop_write_jump_functions (set);
699 }
700
701
702 /* Release inline summary.  */
703
704 void
705 inline_free_summary (void)
706 {
707   if (function_insertion_hook_holder)
708     cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
709   function_insertion_hook_holder = NULL;
710   if (node_removal_hook_holder)
711     cgraph_remove_node_removal_hook (node_removal_hook_holder);
712   node_removal_hook_holder = NULL;
713   if (node_duplication_hook_holder)
714     cgraph_remove_node_duplication_hook (node_duplication_hook_holder);
715   node_duplication_hook_holder = NULL;
716   VEC_free (inline_summary_t, heap, inline_summary_vec);
717 }