cgraphbuild.c: Include ipa-inline.h.
[gcc.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->time = info->self_time = lto_input_uleb128 (ib);
616 info->time_inlining_benefit = lto_input_uleb128 (ib);
617 info->size = info->self_size = lto_input_uleb128 (ib);
618 info->size_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 }