Mercurial > hg > CbC > CbC_gcc
comparison gcc/ipa-inline.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
comparison
equal
deleted
inserted
replaced
56:3c8a44c06a95 | 63:b7f97abdc517 |
---|---|
1 /* Inlining decision heuristics. | 1 /* Inlining decision heuristics. |
2 Copyright (C) 2003, 2004, 2007, 2008, 2009 Free Software Foundation, Inc. | 2 Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010 |
3 Free Software Foundation, Inc. | |
3 Contributed by Jan Hubicka | 4 Contributed by Jan Hubicka |
4 | 5 |
5 This file is part of GCC. | 6 This file is part of GCC. |
6 | 7 |
7 GCC is free software; you can redistribute it and/or modify it under | 8 GCC is free software; you can redistribute it and/or modify it under |
125 #include "tree-inline.h" | 126 #include "tree-inline.h" |
126 #include "langhooks.h" | 127 #include "langhooks.h" |
127 #include "flags.h" | 128 #include "flags.h" |
128 #include "cgraph.h" | 129 #include "cgraph.h" |
129 #include "diagnostic.h" | 130 #include "diagnostic.h" |
131 #include "gimple-pretty-print.h" | |
130 #include "timevar.h" | 132 #include "timevar.h" |
131 #include "params.h" | 133 #include "params.h" |
132 #include "fibheap.h" | 134 #include "fibheap.h" |
133 #include "intl.h" | 135 #include "intl.h" |
134 #include "tree-pass.h" | 136 #include "tree-pass.h" |
157 INLINE_ALWAYS_INLINE, | 159 INLINE_ALWAYS_INLINE, |
158 INLINE_SIZE_NORECURSIVE, | 160 INLINE_SIZE_NORECURSIVE, |
159 INLINE_SIZE, | 161 INLINE_SIZE, |
160 INLINE_ALL | 162 INLINE_ALL |
161 }; | 163 }; |
164 | |
162 static bool | 165 static bool |
163 cgraph_decide_inlining_incrementally (struct cgraph_node *, enum inlining_mode, | 166 cgraph_decide_inlining_incrementally (struct cgraph_node *, enum inlining_mode); |
164 int); | 167 static void cgraph_flatten (struct cgraph_node *node); |
165 | 168 |
166 | 169 |
167 /* Statistics we collect about inlining algorithm. */ | 170 /* Statistics we collect about inlining algorithm. */ |
168 static int ncalls_inlined; | 171 static int ncalls_inlined; |
169 static int nfunctions_inlined; | 172 static int nfunctions_inlined; |
264 update_noncloned_frequencies (e->callee, e->frequency, e->loop_nest); | 267 update_noncloned_frequencies (e->callee, e->frequency, e->loop_nest); |
265 } | 268 } |
266 else | 269 else |
267 { | 270 { |
268 struct cgraph_node *n; | 271 struct cgraph_node *n; |
269 n = cgraph_clone_node (e->callee, e->count, e->frequency, e->loop_nest, | 272 n = cgraph_clone_node (e->callee, e->callee->decl, |
273 e->count, e->frequency, e->loop_nest, | |
270 update_original, NULL); | 274 update_original, NULL); |
271 cgraph_redirect_edge_callee (e, n); | 275 cgraph_redirect_edge_callee (e, n); |
272 } | 276 } |
273 } | 277 } |
274 | 278 |
281 + inline_summary (e->caller)->estimated_self_stack_size; | 285 + inline_summary (e->caller)->estimated_self_stack_size; |
282 peak = e->callee->global.stack_frame_offset | 286 peak = e->callee->global.stack_frame_offset |
283 + inline_summary (e->callee)->estimated_self_stack_size; | 287 + inline_summary (e->callee)->estimated_self_stack_size; |
284 if (e->callee->global.inlined_to->global.estimated_stack_size < peak) | 288 if (e->callee->global.inlined_to->global.estimated_stack_size < peak) |
285 e->callee->global.inlined_to->global.estimated_stack_size = peak; | 289 e->callee->global.inlined_to->global.estimated_stack_size = peak; |
290 cgraph_propagate_frequency (e->callee); | |
286 | 291 |
287 /* Recursively clone all bodies. */ | 292 /* Recursively clone all bodies. */ |
288 for (e = e->callee->callees; e; e = e->next_callee) | 293 for (e = e->callee->callees; e; e = e->next_callee) |
289 if (!e->inline_failed) | 294 if (!e->inline_failed) |
290 cgraph_clone_inlined_nodes (e, duplicate, update_original); | 295 cgraph_clone_inlined_nodes (e, duplicate, update_original); |
302 { | 307 { |
303 int old_size = 0, new_size = 0; | 308 int old_size = 0, new_size = 0; |
304 struct cgraph_node *to = NULL, *what; | 309 struct cgraph_node *to = NULL, *what; |
305 struct cgraph_edge *curr = e; | 310 struct cgraph_edge *curr = e; |
306 int freq; | 311 int freq; |
307 bool duplicate = false; | |
308 int orig_size = e->callee->global.size; | |
309 | 312 |
310 gcc_assert (e->inline_failed); | 313 gcc_assert (e->inline_failed); |
311 e->inline_failed = CIF_OK; | 314 e->inline_failed = CIF_OK; |
312 | 315 DECL_POSSIBLY_INLINED (e->callee->decl) = true; |
313 if (!e->callee->global.inlined) | 316 |
314 DECL_POSSIBLY_INLINED (e->callee->decl) = true; | |
315 e->callee->global.inlined = true; | |
316 | |
317 if (e->callee->callers->next_caller | |
318 || !cgraph_can_remove_if_no_direct_calls_p (e->callee) | |
319 || e->callee->same_comdat_group) | |
320 duplicate = true; | |
321 cgraph_clone_inlined_nodes (e, true, update_original); | 317 cgraph_clone_inlined_nodes (e, true, update_original); |
322 | 318 |
323 what = e->callee; | 319 what = e->callee; |
324 | 320 |
325 freq = e->frequency; | 321 freq = e->frequency; |
333 to->global.time = cgraph_estimate_time_after_inlining (freq, to, what); | 329 to->global.time = cgraph_estimate_time_after_inlining (freq, to, what); |
334 } | 330 } |
335 gcc_assert (what->global.inlined_to == to); | 331 gcc_assert (what->global.inlined_to == to); |
336 if (new_size > old_size) | 332 if (new_size > old_size) |
337 overall_size += new_size - old_size; | 333 overall_size += new_size - old_size; |
338 if (!duplicate) | |
339 overall_size -= orig_size; | |
340 ncalls_inlined++; | 334 ncalls_inlined++; |
341 | 335 |
342 if (flag_indirect_inlining) | 336 if (flag_indirect_inlining) |
343 return ipa_propagate_indirect_call_infos (curr, new_edges); | 337 return ipa_propagate_indirect_call_infos (curr, new_edges); |
344 else | 338 else |
345 return false; | 339 return false; |
346 } | 340 } |
347 | 341 |
348 /* Mark all calls of EDGE->CALLEE inlined into EDGE->CALLER. | 342 /* Mark all calls of EDGE->CALLEE inlined into EDGE->CALLER. */ |
349 Return following unredirected edge in the list of callers | 343 |
350 of EDGE->CALLEE */ | 344 static void |
351 | |
352 static struct cgraph_edge * | |
353 cgraph_mark_inline (struct cgraph_edge *edge) | 345 cgraph_mark_inline (struct cgraph_edge *edge) |
354 { | 346 { |
355 struct cgraph_node *to = edge->caller; | 347 struct cgraph_node *to = edge->caller; |
356 struct cgraph_node *what = edge->callee; | 348 struct cgraph_node *what = edge->callee; |
357 struct cgraph_edge *e, *next; | 349 struct cgraph_edge *e, *next; |
367 cgraph_mark_inline_edge (e, true, NULL); | 359 cgraph_mark_inline_edge (e, true, NULL); |
368 if (e == edge) | 360 if (e == edge) |
369 edge = next; | 361 edge = next; |
370 } | 362 } |
371 } | 363 } |
372 | |
373 return edge; | |
374 } | 364 } |
375 | 365 |
376 /* Estimate the growth caused by inlining NODE into all callees. */ | 366 /* Estimate the growth caused by inlining NODE into all callees. */ |
377 | 367 |
378 static int | 368 static int |
475 | 465 |
476 static bool | 466 static bool |
477 cgraph_default_inline_p (struct cgraph_node *n, cgraph_inline_failed_t *reason) | 467 cgraph_default_inline_p (struct cgraph_node *n, cgraph_inline_failed_t *reason) |
478 { | 468 { |
479 tree decl = n->decl; | 469 tree decl = n->decl; |
470 | |
471 if (n->local.disregard_inline_limits) | |
472 return true; | |
480 | 473 |
481 if (!flag_inline_small_functions && !DECL_DECLARED_INLINE_P (decl)) | 474 if (!flag_inline_small_functions && !DECL_DECLARED_INLINE_P (decl)) |
482 { | 475 { |
483 if (reason) | 476 if (reason) |
484 *reason = CIF_FUNCTION_NOT_INLINE_CANDIDATE; | 477 *reason = CIF_FUNCTION_NOT_INLINE_CANDIDATE; |
541 the costs of all caller edges of nodes affected are recomputed so the | 534 the costs of all caller edges of nodes affected are recomputed so the |
542 metrics may accurately depend on values such as number of inlinable callers | 535 metrics may accurately depend on values such as number of inlinable callers |
543 of the function or function body size. */ | 536 of the function or function body size. */ |
544 | 537 |
545 static int | 538 static int |
546 cgraph_edge_badness (struct cgraph_edge *edge) | 539 cgraph_edge_badness (struct cgraph_edge *edge, bool dump) |
547 { | 540 { |
548 gcov_type badness; | 541 gcov_type badness; |
549 int growth = | 542 int growth = |
550 cgraph_estimate_size_after_inlining (1, edge->caller, edge->callee); | 543 (cgraph_estimate_size_after_inlining (1, edge->caller, edge->callee) |
551 | 544 - edge->caller->global.size); |
552 growth -= edge->caller->global.size; | 545 |
546 if (edge->callee->local.disregard_inline_limits) | |
547 return INT_MIN; | |
548 | |
549 if (dump) | |
550 { | |
551 fprintf (dump_file, " Badness calculcation for %s -> %s\n", | |
552 cgraph_node_name (edge->caller), | |
553 cgraph_node_name (edge->callee)); | |
554 fprintf (dump_file, " growth %i, time %i-%i, size %i-%i\n", | |
555 growth, | |
556 edge->callee->global.time, | |
557 inline_summary (edge->callee)->time_inlining_benefit, | |
558 edge->callee->global.size, | |
559 inline_summary (edge->callee)->size_inlining_benefit); | |
560 } | |
553 | 561 |
554 /* Always prefer inlining saving code size. */ | 562 /* Always prefer inlining saving code size. */ |
555 if (growth <= 0) | 563 if (growth <= 0) |
556 badness = INT_MIN - growth; | 564 { |
565 badness = INT_MIN - growth; | |
566 if (dump) | |
567 fprintf (dump_file, " %i: Growth %i < 0\n", (int) badness, | |
568 growth); | |
569 } | |
557 | 570 |
558 /* When profiling is available, base priorities -(#calls / growth). | 571 /* When profiling is available, base priorities -(#calls / growth). |
559 So we optimize for overall number of "executed" inlined calls. */ | 572 So we optimize for overall number of "executed" inlined calls. */ |
560 else if (max_count) | 573 else if (max_count) |
561 badness = ((int)((double)edge->count * INT_MIN / max_count / (max_benefit + 1)) | 574 { |
562 * (inline_summary (edge->callee)->time_inlining_benefit + 1)) / growth; | 575 badness = |
576 ((int) | |
577 ((double) edge->count * INT_MIN / max_count / (max_benefit + 1)) * | |
578 (inline_summary (edge->callee)->time_inlining_benefit + 1)) / growth; | |
579 if (dump) | |
580 { | |
581 fprintf (dump_file, | |
582 " %i (relative %f): profile info. Relative count %f" | |
583 " * Relative benefit %f\n", | |
584 (int) badness, (double) badness / INT_MIN, | |
585 (double) edge->count / max_count, | |
586 (double) (inline_summary (edge->callee)-> | |
587 time_inlining_benefit + 1) / (max_benefit + 1)); | |
588 } | |
589 } | |
563 | 590 |
564 /* When function local profile is available, base priorities on | 591 /* When function local profile is available, base priorities on |
565 growth / frequency, so we optimize for overall frequency of inlined | 592 growth / frequency, so we optimize for overall frequency of inlined |
566 calls. This is not too accurate since while the call might be frequent | 593 calls. This is not too accurate since while the call might be frequent |
567 within function, the function itself is infrequent. | 594 within function, the function itself is infrequent. |
571 priorities slightly in this direction (so fewer times called functions | 598 priorities slightly in this direction (so fewer times called functions |
572 of the same size gets priority). */ | 599 of the same size gets priority). */ |
573 else if (flag_guess_branch_prob) | 600 else if (flag_guess_branch_prob) |
574 { | 601 { |
575 int div = edge->frequency * 100 / CGRAPH_FREQ_BASE + 1; | 602 int div = edge->frequency * 100 / CGRAPH_FREQ_BASE + 1; |
603 int benefitperc; | |
604 int growth_for_all; | |
576 badness = growth * 10000; | 605 badness = growth * 10000; |
577 div *= MIN (100 * inline_summary (edge->callee)->time_inlining_benefit | 606 benefitperc = |
578 / (edge->callee->global.time + 1) + 1, 100); | 607 MIN (100 * inline_summary (edge->callee)->time_inlining_benefit / |
608 (edge->callee->global.time + 1) +1, 100); | |
609 div *= benefitperc; | |
579 | 610 |
580 | 611 |
581 /* Decrease badness if call is nested. */ | 612 /* Decrease badness if call is nested. */ |
582 /* Compress the range so we don't overflow. */ | 613 /* Compress the range so we don't overflow. */ |
583 if (div > 10000) | 614 if (div > 10000) |
584 div = 10000 + ceil_log2 (div) - 8; | 615 div = 10000 + ceil_log2 (div) - 8; |
585 if (div < 1) | 616 if (div < 1) |
586 div = 1; | 617 div = 1; |
587 if (badness > 0) | 618 if (badness > 0) |
588 badness /= div; | 619 badness /= div; |
589 badness += cgraph_estimate_growth (edge->callee); | 620 growth_for_all = cgraph_estimate_growth (edge->callee); |
621 badness += growth_for_all; | |
590 if (badness > INT_MAX) | 622 if (badness > INT_MAX) |
591 badness = INT_MAX; | 623 badness = INT_MAX; |
624 if (dump) | |
625 { | |
626 fprintf (dump_file, | |
627 " %i: guessed profile. frequency %i, overall growth %i," | |
628 " benefit %i%%, divisor %i\n", | |
629 (int) badness, edge->frequency, growth_for_all, benefitperc, div); | |
630 } | |
592 } | 631 } |
593 /* When function local profile is not available or it does not give | 632 /* When function local profile is not available or it does not give |
594 useful information (ie frequency is zero), base the cost on | 633 useful information (ie frequency is zero), base the cost on |
595 loop nest and overall size growth, so we optimize for overall number | 634 loop nest and overall size growth, so we optimize for overall number |
596 of functions fully inlined in program. */ | 635 of functions fully inlined in program. */ |
601 | 640 |
602 /* Decrease badness if call is nested. */ | 641 /* Decrease badness if call is nested. */ |
603 if (badness > 0) | 642 if (badness > 0) |
604 badness >>= nest; | 643 badness >>= nest; |
605 else | 644 else |
606 { | 645 { |
607 badness <<= nest; | 646 badness <<= nest; |
608 } | 647 } |
609 } | 648 if (dump) |
649 fprintf (dump_file, " %i: no profile. nest %i\n", (int) badness, | |
650 nest); | |
651 } | |
652 | |
653 /* Ensure that we did not overflow in all the fixed point math above. */ | |
654 gcc_assert (badness >= INT_MIN); | |
655 gcc_assert (badness <= INT_MAX - 1); | |
610 /* Make recursive inlining happen always after other inlining is done. */ | 656 /* Make recursive inlining happen always after other inlining is done. */ |
611 if (cgraph_recursive_inlining_p (edge->caller, edge->callee, NULL)) | 657 if (cgraph_recursive_inlining_p (edge->caller, edge->callee, NULL)) |
612 return badness + 1; | 658 return badness + 1; |
613 else | 659 else |
614 return badness; | 660 return badness; |
621 bitmap updated_nodes) | 667 bitmap updated_nodes) |
622 { | 668 { |
623 struct cgraph_edge *edge; | 669 struct cgraph_edge *edge; |
624 cgraph_inline_failed_t failed_reason; | 670 cgraph_inline_failed_t failed_reason; |
625 | 671 |
626 if (!node->local.inlinable || node->local.disregard_inline_limits | 672 if (!node->local.inlinable |
627 || node->global.inlined_to) | 673 || node->global.inlined_to) |
628 return; | 674 return; |
629 if (bitmap_bit_p (updated_nodes, node->uid)) | 675 if (bitmap_bit_p (updated_nodes, node->uid)) |
630 return; | 676 return; |
631 bitmap_set_bit (updated_nodes, node->uid); | 677 bitmap_set_bit (updated_nodes, node->uid); |
648 } | 694 } |
649 | 695 |
650 for (edge = node->callers; edge; edge = edge->next_caller) | 696 for (edge = node->callers; edge; edge = edge->next_caller) |
651 if (edge->inline_failed) | 697 if (edge->inline_failed) |
652 { | 698 { |
653 int badness = cgraph_edge_badness (edge); | 699 int badness = cgraph_edge_badness (edge, false); |
654 if (edge->aux) | 700 if (edge->aux) |
655 { | 701 { |
656 fibnode_t n = (fibnode_t) edge->aux; | 702 fibnode_t n = (fibnode_t) edge->aux; |
657 gcc_assert (n->data == edge); | 703 gcc_assert (n->data == edge); |
658 if (n->key == badness) | 704 if (n->key == badness) |
659 continue; | 705 continue; |
660 | 706 |
661 /* fibheap_replace_key only increase the keys. */ | 707 /* fibheap_replace_key only increase the keys. */ |
662 if (fibheap_replace_key (heap, n, badness)) | 708 if (badness < n->key) |
663 continue; | 709 { |
710 fibheap_replace_key (heap, n, badness); | |
711 gcc_assert (n->key == badness); | |
712 continue; | |
713 } | |
664 fibheap_delete_node (heap, (fibnode_t) edge->aux); | 714 fibheap_delete_node (heap, (fibnode_t) edge->aux); |
665 } | 715 } |
666 edge->aux = fibheap_insert (heap, badness, edge); | 716 edge->aux = fibheap_insert (heap, badness, edge); |
667 } | 717 } |
668 } | 718 } |
724 struct cgraph_edge *e; | 774 struct cgraph_edge *e; |
725 struct cgraph_node *master_clone, *next; | 775 struct cgraph_node *master_clone, *next; |
726 int depth = 0; | 776 int depth = 0; |
727 int n = 0; | 777 int n = 0; |
728 | 778 |
779 /* It does not make sense to recursively inline always-inline functions | |
780 as we are going to sorry() on the remaining calls anyway. */ | |
781 if (node->local.disregard_inline_limits | |
782 && lookup_attribute ("always_inline", DECL_ATTRIBUTES (node->decl))) | |
783 return false; | |
784 | |
729 if (optimize_function_for_size_p (DECL_STRUCT_FUNCTION (node->decl)) | 785 if (optimize_function_for_size_p (DECL_STRUCT_FUNCTION (node->decl)) |
730 || (!flag_inline_functions && !DECL_DECLARED_INLINE_P (node->decl))) | 786 || (!flag_inline_functions && !DECL_DECLARED_INLINE_P (node->decl))) |
731 return false; | 787 return false; |
732 | 788 |
733 if (DECL_DECLARED_INLINE_P (node->decl)) | 789 if (DECL_DECLARED_INLINE_P (node->decl)) |
752 fprintf (dump_file, | 808 fprintf (dump_file, |
753 " Performing recursive inlining on %s\n", | 809 " Performing recursive inlining on %s\n", |
754 cgraph_node_name (node)); | 810 cgraph_node_name (node)); |
755 | 811 |
756 /* We need original clone to copy around. */ | 812 /* We need original clone to copy around. */ |
757 master_clone = cgraph_clone_node (node, node->count, CGRAPH_FREQ_BASE, 1, | 813 master_clone = cgraph_clone_node (node, node->decl, |
814 node->count, CGRAPH_FREQ_BASE, 1, | |
758 false, NULL); | 815 false, NULL); |
759 master_clone->needed = true; | 816 master_clone->needed = true; |
760 for (e = master_clone->callees; e; e = e->next_callee) | 817 for (e = master_clone->callees; e; e = e->next_callee) |
761 if (!e->inline_failed) | 818 if (!e->inline_failed) |
762 cgraph_clone_inlined_nodes (e, true, false); | 819 cgraph_clone_inlined_nodes (e, true, false); |
880 while (VEC_length (cgraph_edge_p, new_edges) > 0) | 937 while (VEC_length (cgraph_edge_p, new_edges) > 0) |
881 { | 938 { |
882 struct cgraph_edge *edge = VEC_pop (cgraph_edge_p, new_edges); | 939 struct cgraph_edge *edge = VEC_pop (cgraph_edge_p, new_edges); |
883 | 940 |
884 gcc_assert (!edge->aux); | 941 gcc_assert (!edge->aux); |
885 edge->aux = fibheap_insert (heap, cgraph_edge_badness (edge), edge); | 942 edge->aux = fibheap_insert (heap, cgraph_edge_badness (edge, false), edge); |
886 } | 943 } |
887 } | 944 } |
888 | 945 |
889 | 946 |
890 /* We use greedy algorithm for inlining of small functions: | 947 /* We use greedy algorithm for inlining of small functions: |
913 | 970 |
914 /* Put all inline candidates into the heap. */ | 971 /* Put all inline candidates into the heap. */ |
915 | 972 |
916 for (node = cgraph_nodes; node; node = node->next) | 973 for (node = cgraph_nodes; node; node = node->next) |
917 { | 974 { |
918 if (!node->local.inlinable || !node->callers | 975 if (!node->local.inlinable || !node->callers) |
919 || node->local.disregard_inline_limits) | |
920 continue; | 976 continue; |
921 if (dump_file) | 977 if (dump_file) |
922 fprintf (dump_file, "Considering inline candidate %s.\n", cgraph_node_name (node)); | 978 fprintf (dump_file, "Considering inline candidate %s.\n", cgraph_node_name (node)); |
923 | 979 |
924 node->global.estimated_growth = INT_MIN; | 980 node->global.estimated_growth = INT_MIN; |
930 | 986 |
931 for (edge = node->callers; edge; edge = edge->next_caller) | 987 for (edge = node->callers; edge; edge = edge->next_caller) |
932 if (edge->inline_failed) | 988 if (edge->inline_failed) |
933 { | 989 { |
934 gcc_assert (!edge->aux); | 990 gcc_assert (!edge->aux); |
935 edge->aux = fibheap_insert (heap, cgraph_edge_badness (edge), edge); | 991 edge->aux = fibheap_insert (heap, cgraph_edge_badness (edge, false), edge); |
936 } | 992 } |
937 } | 993 } |
938 | 994 |
939 max_size = compute_max_insns (overall_size); | 995 max_size = compute_max_insns (overall_size); |
940 min_size = overall_size; | 996 min_size = overall_size; |
941 | 997 |
942 while (overall_size <= max_size | 998 while (overall_size <= max_size |
943 && (edge = (struct cgraph_edge *) fibheap_extract_min (heap))) | 999 && !fibheap_empty (heap)) |
944 { | 1000 { |
945 int old_size = overall_size; | 1001 int old_size = overall_size; |
946 struct cgraph_node *where; | 1002 struct cgraph_node *where, *callee; |
947 int growth = | 1003 int badness = fibheap_min_key (heap); |
948 cgraph_estimate_size_after_inlining (1, edge->caller, edge->callee); | 1004 int growth; |
949 cgraph_inline_failed_t not_good = CIF_OK; | 1005 cgraph_inline_failed_t not_good = CIF_OK; |
950 | 1006 |
951 growth -= edge->caller->global.size; | 1007 edge = (struct cgraph_edge *) fibheap_extract_min (heap); |
1008 gcc_assert (edge->aux); | |
1009 edge->aux = NULL; | |
1010 if (!edge->inline_failed) | |
1011 continue; | |
1012 #ifdef ENABLE_CHECKING | |
1013 gcc_assert (cgraph_edge_badness (edge, false) == badness); | |
1014 #endif | |
1015 callee = edge->callee; | |
1016 | |
1017 growth = (cgraph_estimate_size_after_inlining (1, edge->caller, edge->callee) | |
1018 - edge->caller->global.size); | |
952 | 1019 |
953 if (dump_file) | 1020 if (dump_file) |
954 { | 1021 { |
955 fprintf (dump_file, | 1022 fprintf (dump_file, |
956 "\nConsidering %s with %i size\n", | 1023 "\nConsidering %s with %i size\n", |
959 fprintf (dump_file, | 1026 fprintf (dump_file, |
960 " to be inlined into %s in %s:%i\n" | 1027 " to be inlined into %s in %s:%i\n" |
961 " Estimated growth after inlined into all callees is %+i insns.\n" | 1028 " Estimated growth after inlined into all callees is %+i insns.\n" |
962 " Estimated badness is %i, frequency %.2f.\n", | 1029 " Estimated badness is %i, frequency %.2f.\n", |
963 cgraph_node_name (edge->caller), | 1030 cgraph_node_name (edge->caller), |
964 gimple_filename ((const_gimple) edge->call_stmt), | 1031 flag_wpa ? "unknown" |
965 gimple_lineno ((const_gimple) edge->call_stmt), | 1032 : gimple_filename ((const_gimple) edge->call_stmt), |
1033 flag_wpa ? -1 : gimple_lineno ((const_gimple) edge->call_stmt), | |
966 cgraph_estimate_growth (edge->callee), | 1034 cgraph_estimate_growth (edge->callee), |
967 cgraph_edge_badness (edge), | 1035 badness, |
968 edge->frequency / (double)CGRAPH_FREQ_BASE); | 1036 edge->frequency / (double)CGRAPH_FREQ_BASE); |
969 if (edge->count) | 1037 if (edge->count) |
970 fprintf (dump_file," Called "HOST_WIDEST_INT_PRINT_DEC"x\n", edge->count); | 1038 fprintf (dump_file," Called "HOST_WIDEST_INT_PRINT_DEC"x\n", edge->count); |
971 } | 1039 if (dump_flags & TDF_DETAILS) |
972 gcc_assert (edge->aux); | 1040 cgraph_edge_badness (edge, true); |
973 edge->aux = NULL; | 1041 } |
974 if (!edge->inline_failed) | |
975 continue; | |
976 | 1042 |
977 /* When not having profile info ready we don't weight by any way the | 1043 /* When not having profile info ready we don't weight by any way the |
978 position of call in procedure itself. This means if call of | 1044 position of call in procedure itself. This means if call of |
979 function A from function B seems profitable to inline, the recursive | 1045 function A from function B seems profitable to inline, the recursive |
980 call of function A in inline copy of A in B will look profitable too | 1046 call of function A in inline copy of A in B will look profitable too |
1006 fprintf (dump_file, " inline_failed:Recursive inlining performed only for function itself.\n"); | 1072 fprintf (dump_file, " inline_failed:Recursive inlining performed only for function itself.\n"); |
1007 continue; | 1073 continue; |
1008 } | 1074 } |
1009 } | 1075 } |
1010 | 1076 |
1011 if (!cgraph_maybe_hot_edge_p (edge)) | 1077 if (edge->callee->local.disregard_inline_limits) |
1078 ; | |
1079 else if (!cgraph_maybe_hot_edge_p (edge)) | |
1012 not_good = CIF_UNLIKELY_CALL; | 1080 not_good = CIF_UNLIKELY_CALL; |
1013 if (!flag_inline_functions | 1081 else if (!flag_inline_functions |
1014 && !DECL_DECLARED_INLINE_P (edge->callee->decl)) | 1082 && !DECL_DECLARED_INLINE_P (edge->callee->decl)) |
1015 not_good = CIF_NOT_DECLARED_INLINED; | 1083 not_good = CIF_NOT_DECLARED_INLINED; |
1016 if (optimize_function_for_size_p (DECL_STRUCT_FUNCTION(edge->caller->decl))) | 1084 else if (optimize_function_for_size_p (DECL_STRUCT_FUNCTION(edge->caller->decl))) |
1017 not_good = CIF_OPTIMIZING_FOR_SIZE; | 1085 not_good = CIF_OPTIMIZING_FOR_SIZE; |
1018 if (not_good && growth > 0 && cgraph_estimate_growth (edge->callee) > 0) | 1086 if (not_good && growth > 0 && cgraph_estimate_growth (edge->callee) > 0) |
1019 { | 1087 { |
1020 if (!cgraph_recursive_inlining_p (edge->caller, edge->callee, | 1088 if (!cgraph_recursive_inlining_p (edge->caller, edge->callee, |
1021 &edge->inline_failed)) | 1089 &edge->inline_failed)) |
1088 After inlining these properties might change for the function we | 1156 After inlining these properties might change for the function we |
1089 inlined into (since it's body size changed) and for the functions | 1157 inlined into (since it's body size changed) and for the functions |
1090 called by function we inlined (since number of it inlinable callers | 1158 called by function we inlined (since number of it inlinable callers |
1091 might change). */ | 1159 might change). */ |
1092 update_caller_keys (heap, where, updated_nodes); | 1160 update_caller_keys (heap, where, updated_nodes); |
1161 | |
1162 /* We removed one call of the function we just inlined. If offline | |
1163 copy is still needed, be sure to update the keys. */ | |
1164 if (callee != where && !callee->global.inlined_to) | |
1165 update_caller_keys (heap, callee, updated_nodes); | |
1093 bitmap_clear (updated_nodes); | 1166 bitmap_clear (updated_nodes); |
1094 | 1167 |
1095 if (dump_file) | 1168 if (dump_file) |
1096 { | 1169 { |
1097 fprintf (dump_file, | 1170 fprintf (dump_file, |
1109 | 1182 |
1110 if (dump_file) | 1183 if (dump_file) |
1111 fprintf (dump_file, "New minimal size reached: %i\n", min_size); | 1184 fprintf (dump_file, "New minimal size reached: %i\n", min_size); |
1112 } | 1185 } |
1113 } | 1186 } |
1114 while ((edge = (struct cgraph_edge *) fibheap_extract_min (heap)) != NULL) | 1187 while (!fibheap_empty (heap)) |
1115 { | 1188 { |
1189 int badness = fibheap_min_key (heap); | |
1190 | |
1191 edge = (struct cgraph_edge *) fibheap_extract_min (heap); | |
1116 gcc_assert (edge->aux); | 1192 gcc_assert (edge->aux); |
1117 edge->aux = NULL; | 1193 edge->aux = NULL; |
1194 if (!edge->inline_failed) | |
1195 continue; | |
1196 #ifdef ENABLE_CHECKING | |
1197 gcc_assert (cgraph_edge_badness (edge, false) == badness); | |
1198 #endif | |
1199 if (dump_file) | |
1200 { | |
1201 fprintf (dump_file, | |
1202 "\nSkipping %s with %i size\n", | |
1203 cgraph_node_name (edge->callee), | |
1204 edge->callee->global.size); | |
1205 fprintf (dump_file, | |
1206 " called by %s in %s:%i\n" | |
1207 " Estimated growth after inlined into all callees is %+i insns.\n" | |
1208 " Estimated badness is %i, frequency %.2f.\n", | |
1209 cgraph_node_name (edge->caller), | |
1210 flag_wpa ? "unknown" | |
1211 : gimple_filename ((const_gimple) edge->call_stmt), | |
1212 flag_wpa ? -1 : gimple_lineno ((const_gimple) edge->call_stmt), | |
1213 cgraph_estimate_growth (edge->callee), | |
1214 badness, | |
1215 edge->frequency / (double)CGRAPH_FREQ_BASE); | |
1216 if (edge->count) | |
1217 fprintf (dump_file," Called "HOST_WIDEST_INT_PRINT_DEC"x\n", edge->count); | |
1218 if (dump_flags & TDF_DETAILS) | |
1219 cgraph_edge_badness (edge, true); | |
1220 } | |
1118 if (!edge->callee->local.disregard_inline_limits && edge->inline_failed | 1221 if (!edge->callee->local.disregard_inline_limits && edge->inline_failed |
1119 && !cgraph_recursive_inlining_p (edge->caller, edge->callee, | 1222 && !cgraph_recursive_inlining_p (edge->caller, edge->callee, |
1120 &edge->inline_failed)) | 1223 &edge->inline_failed)) |
1121 edge->inline_failed = CIF_INLINE_UNIT_GROWTH_LIMIT; | 1224 edge->inline_failed = CIF_INLINE_UNIT_GROWTH_LIMIT; |
1122 } | 1225 } |
1123 | 1226 |
1124 if (new_indirect_edges) | 1227 if (new_indirect_edges) |
1125 VEC_free (cgraph_edge_p, heap, new_indirect_edges); | 1228 VEC_free (cgraph_edge_p, heap, new_indirect_edges); |
1126 fibheap_delete (heap); | 1229 fibheap_delete (heap); |
1127 BITMAP_FREE (updated_nodes); | 1230 BITMAP_FREE (updated_nodes); |
1231 } | |
1232 | |
1233 /* Flatten NODE from the IPA inliner. */ | |
1234 | |
1235 static void | |
1236 cgraph_flatten (struct cgraph_node *node) | |
1237 { | |
1238 struct cgraph_edge *e; | |
1239 | |
1240 /* We shouldn't be called recursively when we are being processed. */ | |
1241 gcc_assert (node->aux == NULL); | |
1242 | |
1243 node->aux = (void *)(size_t) INLINE_ALL; | |
1244 | |
1245 for (e = node->callees; e; e = e->next_callee) | |
1246 { | |
1247 struct cgraph_node *orig_callee; | |
1248 | |
1249 if (e->call_stmt_cannot_inline_p) | |
1250 continue; | |
1251 | |
1252 if (!e->callee->analyzed) | |
1253 { | |
1254 if (dump_file) | |
1255 fprintf (dump_file, | |
1256 "Not inlining: Function body not available.\n"); | |
1257 continue; | |
1258 } | |
1259 | |
1260 /* We've hit cycle? It is time to give up. */ | |
1261 if (e->callee->aux) | |
1262 { | |
1263 if (dump_file) | |
1264 fprintf (dump_file, | |
1265 "Not inlining %s into %s to avoid cycle.\n", | |
1266 cgraph_node_name (e->callee), | |
1267 cgraph_node_name (e->caller)); | |
1268 e->inline_failed = CIF_RECURSIVE_INLINING; | |
1269 continue; | |
1270 } | |
1271 | |
1272 /* When the edge is already inlined, we just need to recurse into | |
1273 it in order to fully flatten the leaves. */ | |
1274 if (!e->inline_failed) | |
1275 { | |
1276 cgraph_flatten (e->callee); | |
1277 continue; | |
1278 } | |
1279 | |
1280 if (cgraph_recursive_inlining_p (node, e->callee, &e->inline_failed)) | |
1281 { | |
1282 if (dump_file) | |
1283 fprintf (dump_file, "Not inlining: recursive call.\n"); | |
1284 continue; | |
1285 } | |
1286 | |
1287 if (!tree_can_inline_p (e)) | |
1288 { | |
1289 if (dump_file) | |
1290 fprintf (dump_file, "Not inlining: %s", | |
1291 cgraph_inline_failed_string (e->inline_failed)); | |
1292 continue; | |
1293 } | |
1294 | |
1295 /* Inline the edge and flatten the inline clone. Avoid | |
1296 recursing through the original node if the node was cloned. */ | |
1297 if (dump_file) | |
1298 fprintf (dump_file, " Inlining %s into %s.\n", | |
1299 cgraph_node_name (e->callee), | |
1300 cgraph_node_name (e->caller)); | |
1301 orig_callee = e->callee; | |
1302 cgraph_mark_inline_edge (e, true, NULL); | |
1303 if (e->callee != orig_callee) | |
1304 orig_callee->aux = (void *)(size_t) INLINE_ALL; | |
1305 cgraph_flatten (e->callee); | |
1306 if (e->callee != orig_callee) | |
1307 orig_callee->aux = NULL; | |
1308 } | |
1309 | |
1310 node->aux = NULL; | |
1128 } | 1311 } |
1129 | 1312 |
1130 /* Decide on the inlining. We do so in the topological order to avoid | 1313 /* Decide on the inlining. We do so in the topological order to avoid |
1131 expenses on updating data structures. */ | 1314 expenses on updating data structures. */ |
1132 | 1315 |
1137 int nnodes; | 1320 int nnodes; |
1138 struct cgraph_node **order = | 1321 struct cgraph_node **order = |
1139 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes); | 1322 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes); |
1140 int old_size = 0; | 1323 int old_size = 0; |
1141 int i; | 1324 int i; |
1142 bool redo_always_inline = true; | |
1143 int initial_size = 0; | 1325 int initial_size = 0; |
1144 | 1326 |
1145 cgraph_remove_function_insertion_hook (function_insertion_hook_holder); | 1327 cgraph_remove_function_insertion_hook (function_insertion_hook_holder); |
1146 if (in_lto_p && flag_indirect_inlining) | 1328 if (in_lto_p && flag_indirect_inlining) |
1147 ipa_update_after_lto_read (); | 1329 ipa_update_after_lto_read (); |
1330 if (flag_indirect_inlining) | |
1331 ipa_create_all_structures_for_iinln (); | |
1148 | 1332 |
1149 max_count = 0; | 1333 max_count = 0; |
1150 max_benefit = 0; | 1334 max_benefit = 0; |
1151 for (node = cgraph_nodes; node; node = node->next) | 1335 for (node = cgraph_nodes; node; node = node->next) |
1152 if (node->analyzed) | 1336 if (node->analyzed) |
1175 | 1359 |
1176 for (node = cgraph_nodes; node; node = node->next) | 1360 for (node = cgraph_nodes; node; node = node->next) |
1177 node->aux = 0; | 1361 node->aux = 0; |
1178 | 1362 |
1179 if (dump_file) | 1363 if (dump_file) |
1180 fprintf (dump_file, "\nInlining always_inline functions:\n"); | 1364 fprintf (dump_file, "\nFlattening functions:\n"); |
1181 | 1365 |
1182 /* In the first pass mark all always_inline edges. Do this with a priority | 1366 /* In the first pass handle functions to be flattened. Do this with |
1183 so none of our later choices will make this impossible. */ | 1367 a priority so none of our later choices will make this impossible. */ |
1184 while (redo_always_inline) | 1368 for (i = nnodes - 1; i >= 0; i--) |
1185 { | 1369 { |
1186 redo_always_inline = false; | 1370 node = order[i]; |
1187 for (i = nnodes - 1; i >= 0; i--) | 1371 |
1188 { | 1372 /* Handle nodes to be flattened, but don't update overall unit |
1189 struct cgraph_edge *e, *next; | 1373 size. Calling the incremental inliner here is lame, |
1190 | 1374 a simple worklist should be enough. What should be left |
1191 node = order[i]; | 1375 here from the early inliner (if it runs) is cyclic cases. |
1192 | 1376 Ideally when processing callees we stop inlining at the |
1193 /* Handle nodes to be flattened, but don't update overall unit | 1377 entry of cycles, possibly cloning that entry point and |
1194 size. */ | 1378 try to flatten itself turning it into a self-recursive |
1195 if (lookup_attribute ("flatten", | 1379 function. */ |
1196 DECL_ATTRIBUTES (node->decl)) != NULL) | 1380 if (lookup_attribute ("flatten", |
1197 { | 1381 DECL_ATTRIBUTES (node->decl)) != NULL) |
1198 if (dump_file) | 1382 { |
1199 fprintf (dump_file, | |
1200 "Flattening %s\n", cgraph_node_name (node)); | |
1201 cgraph_decide_inlining_incrementally (node, INLINE_ALL, 0); | |
1202 } | |
1203 | |
1204 if (!node->local.disregard_inline_limits) | |
1205 continue; | |
1206 if (dump_file) | 1383 if (dump_file) |
1207 fprintf (dump_file, | 1384 fprintf (dump_file, |
1208 "\nConsidering %s size:%i (always inline)\n", | 1385 "Flattening %s\n", cgraph_node_name (node)); |
1209 cgraph_node_name (node), node->global.size); | 1386 cgraph_flatten (node); |
1210 old_size = overall_size; | |
1211 for (e = node->callers; e; e = next) | |
1212 { | |
1213 next = e->next_caller; | |
1214 if (!e->inline_failed || e->call_stmt_cannot_inline_p) | |
1215 continue; | |
1216 if (cgraph_recursive_inlining_p (e->caller, e->callee, | |
1217 &e->inline_failed)) | |
1218 continue; | |
1219 if (!tree_can_inline_p (e)) | |
1220 continue; | |
1221 if (cgraph_mark_inline_edge (e, true, NULL)) | |
1222 redo_always_inline = true; | |
1223 if (dump_file) | |
1224 fprintf (dump_file, | |
1225 " Inlined into %s which now has size %i.\n", | |
1226 cgraph_node_name (e->caller), | |
1227 e->caller->global.size); | |
1228 } | |
1229 /* Inlining self recursive function might introduce new calls to | |
1230 themselves we didn't see in the loop above. Fill in the proper | |
1231 reason why inline failed. */ | |
1232 for (e = node->callers; e; e = e->next_caller) | |
1233 if (e->inline_failed) | |
1234 e->inline_failed = CIF_RECURSIVE_INLINING; | |
1235 if (dump_file) | |
1236 fprintf (dump_file, | |
1237 " Inlined for a net change of %+i size.\n", | |
1238 overall_size - old_size); | |
1239 } | 1387 } |
1240 } | 1388 } |
1241 | 1389 |
1242 cgraph_decide_inlining_of_small_functions (); | 1390 cgraph_decide_inlining_of_small_functions (); |
1243 | 1391 |
1276 } | 1424 } |
1277 | 1425 |
1278 if (cgraph_check_inline_limits (node->callers->caller, node, | 1426 if (cgraph_check_inline_limits (node->callers->caller, node, |
1279 &reason, false)) | 1427 &reason, false)) |
1280 { | 1428 { |
1429 struct cgraph_node *caller = node->callers->caller; | |
1281 cgraph_mark_inline (node->callers); | 1430 cgraph_mark_inline (node->callers); |
1282 if (dump_file) | 1431 if (dump_file) |
1283 fprintf (dump_file, | 1432 fprintf (dump_file, |
1284 " Inlined into %s which now has %i size" | 1433 " Inlined into %s which now has %i size" |
1285 " for a net change of %+i size.\n", | 1434 " for a net change of %+i size.\n", |
1286 cgraph_node_name (node->callers->caller), | 1435 cgraph_node_name (caller), |
1287 node->callers->caller->global.size, | 1436 caller->global.size, |
1288 overall_size - old_size); | 1437 overall_size - old_size); |
1289 } | 1438 } |
1290 else | 1439 else |
1291 { | 1440 { |
1292 if (dump_file) | 1441 if (dump_file) |
1298 } | 1447 } |
1299 } | 1448 } |
1300 | 1449 |
1301 /* Free ipa-prop structures if they are no longer needed. */ | 1450 /* Free ipa-prop structures if they are no longer needed. */ |
1302 if (flag_indirect_inlining) | 1451 if (flag_indirect_inlining) |
1303 free_all_ipa_structures_after_iinln (); | 1452 ipa_free_all_structures_after_iinln (); |
1304 | 1453 |
1305 if (dump_file) | 1454 if (dump_file) |
1306 fprintf (dump_file, | 1455 fprintf (dump_file, |
1307 "\nInlined %i calls, eliminated %i functions, " | 1456 "\nInlined %i calls, eliminated %i functions, " |
1308 "size %i turned to %i size.\n\n", | 1457 "size %i turned to %i size.\n\n", |
1310 overall_size); | 1459 overall_size); |
1311 free (order); | 1460 free (order); |
1312 return 0; | 1461 return 0; |
1313 } | 1462 } |
1314 | 1463 |
1315 /* Try to inline edge E from incremental inliner. MODE specifies mode | |
1316 of inliner. | |
1317 | |
1318 We are detecting cycles by storing mode of inliner into cgraph_node last | |
1319 time we visited it in the recursion. In general when mode is set, we have | |
1320 recursive inlining, but as an special case, we want to try harder inline | |
1321 ALWAYS_INLINE functions: consider callgraph a->b->c->b, with a being | |
1322 flatten, b being always inline. Flattening 'a' will collapse | |
1323 a->b->c before hitting cycle. To accommodate always inline, we however | |
1324 need to inline a->b->c->b. | |
1325 | |
1326 So after hitting cycle first time, we switch into ALWAYS_INLINE mode and | |
1327 stop inlining only after hitting ALWAYS_INLINE in ALWAY_INLINE mode. */ | |
1328 static bool | |
1329 try_inline (struct cgraph_edge *e, enum inlining_mode mode, int depth) | |
1330 { | |
1331 struct cgraph_node *callee = e->callee; | |
1332 enum inlining_mode callee_mode = (enum inlining_mode) (size_t) callee->aux; | |
1333 bool always_inline = e->callee->local.disregard_inline_limits; | |
1334 bool inlined = false; | |
1335 | |
1336 /* We've hit cycle? */ | |
1337 if (callee_mode) | |
1338 { | |
1339 /* It is first time we see it and we are not in ALWAY_INLINE only | |
1340 mode yet. and the function in question is always_inline. */ | |
1341 if (always_inline && mode != INLINE_ALWAYS_INLINE) | |
1342 { | |
1343 if (dump_file) | |
1344 { | |
1345 indent_to (dump_file, depth); | |
1346 fprintf (dump_file, | |
1347 "Hit cycle in %s, switching to always inline only.\n", | |
1348 cgraph_node_name (callee)); | |
1349 } | |
1350 mode = INLINE_ALWAYS_INLINE; | |
1351 } | |
1352 /* Otherwise it is time to give up. */ | |
1353 else | |
1354 { | |
1355 if (dump_file) | |
1356 { | |
1357 indent_to (dump_file, depth); | |
1358 fprintf (dump_file, | |
1359 "Not inlining %s into %s to avoid cycle.\n", | |
1360 cgraph_node_name (callee), | |
1361 cgraph_node_name (e->caller)); | |
1362 } | |
1363 e->inline_failed = (e->callee->local.disregard_inline_limits | |
1364 ? CIF_RECURSIVE_INLINING : CIF_UNSPECIFIED); | |
1365 return false; | |
1366 } | |
1367 } | |
1368 | |
1369 callee->aux = (void *)(size_t) mode; | |
1370 if (dump_file) | |
1371 { | |
1372 indent_to (dump_file, depth); | |
1373 fprintf (dump_file, " Inlining %s into %s.\n", | |
1374 cgraph_node_name (e->callee), | |
1375 cgraph_node_name (e->caller)); | |
1376 } | |
1377 if (e->inline_failed) | |
1378 { | |
1379 cgraph_mark_inline (e); | |
1380 | |
1381 /* In order to fully inline always_inline functions, we need to | |
1382 recurse here, since the inlined functions might not be processed by | |
1383 incremental inlining at all yet. | |
1384 | |
1385 Also flattening needs to be done recursively. */ | |
1386 | |
1387 if (mode == INLINE_ALL || always_inline) | |
1388 cgraph_decide_inlining_incrementally (e->callee, mode, depth + 1); | |
1389 inlined = true; | |
1390 } | |
1391 callee->aux = (void *)(size_t) callee_mode; | |
1392 return inlined; | |
1393 } | |
1394 | |
1395 /* Return true when N is leaf function. Accept cheap (pure&const) builtins | 1464 /* Return true when N is leaf function. Accept cheap (pure&const) builtins |
1396 in leaf functions. */ | 1465 in leaf functions. */ |
1397 static bool | 1466 static bool |
1398 leaf_node_p (struct cgraph_node *n) | 1467 leaf_node_p (struct cgraph_node *n) |
1399 { | 1468 { |
1405 return false; | 1474 return false; |
1406 return true; | 1475 return true; |
1407 } | 1476 } |
1408 | 1477 |
1409 /* Decide on the inlining. We do so in the topological order to avoid | 1478 /* Decide on the inlining. We do so in the topological order to avoid |
1410 expenses on updating data structures. | 1479 expenses on updating data structures. */ |
1411 DEPTH is depth of recursion, used only for debug output. */ | |
1412 | 1480 |
1413 static bool | 1481 static bool |
1414 cgraph_decide_inlining_incrementally (struct cgraph_node *node, | 1482 cgraph_decide_inlining_incrementally (struct cgraph_node *node, |
1415 enum inlining_mode mode, | 1483 enum inlining_mode mode) |
1416 int depth) | |
1417 { | 1484 { |
1418 struct cgraph_edge *e; | 1485 struct cgraph_edge *e; |
1419 bool inlined = false; | 1486 bool inlined = false; |
1420 cgraph_inline_failed_t failed_reason; | 1487 cgraph_inline_failed_t failed_reason; |
1421 enum inlining_mode old_mode; | |
1422 | 1488 |
1423 #ifdef ENABLE_CHECKING | 1489 #ifdef ENABLE_CHECKING |
1424 verify_cgraph_node (node); | 1490 verify_cgraph_node (node); |
1425 #endif | 1491 #endif |
1426 | 1492 |
1427 old_mode = (enum inlining_mode) (size_t)node->aux; | |
1428 | |
1429 if (mode != INLINE_ALWAYS_INLINE && mode != INLINE_SIZE_NORECURSIVE | 1493 if (mode != INLINE_ALWAYS_INLINE && mode != INLINE_SIZE_NORECURSIVE |
1430 && lookup_attribute ("flatten", DECL_ATTRIBUTES (node->decl)) != NULL) | 1494 && lookup_attribute ("flatten", DECL_ATTRIBUTES (node->decl)) != NULL) |
1431 { | 1495 { |
1432 if (dump_file) | 1496 if (dump_file) |
1433 { | 1497 fprintf (dump_file, "Incrementally flattening %s\n", |
1434 indent_to (dump_file, depth); | 1498 cgraph_node_name (node)); |
1435 fprintf (dump_file, "Flattening %s\n", cgraph_node_name (node)); | |
1436 } | |
1437 mode = INLINE_ALL; | 1499 mode = INLINE_ALL; |
1438 } | 1500 } |
1439 | |
1440 node->aux = (void *)(size_t) mode; | |
1441 | 1501 |
1442 /* First of all look for always inline functions. */ | 1502 /* First of all look for always inline functions. */ |
1443 if (mode != INLINE_SIZE_NORECURSIVE) | 1503 if (mode != INLINE_SIZE_NORECURSIVE) |
1444 for (e = node->callees; e; e = e->next_callee) | 1504 for (e = node->callees; e; e = e->next_callee) |
1445 { | 1505 { |
1446 if (!e->callee->local.disregard_inline_limits | 1506 if (!e->callee->local.disregard_inline_limits |
1447 && (mode != INLINE_ALL || !e->callee->local.inlinable)) | 1507 && (mode != INLINE_ALL || !e->callee->local.inlinable)) |
1448 continue; | 1508 continue; |
1449 if (e->call_stmt_cannot_inline_p) | 1509 if (e->call_stmt_cannot_inline_p) |
1450 continue; | 1510 continue; |
1451 /* When the edge is already inlined, we just need to recurse into | |
1452 it in order to fully flatten the leaves. */ | |
1453 if (!e->inline_failed && mode == INLINE_ALL) | |
1454 { | |
1455 inlined |= try_inline (e, mode, depth); | |
1456 continue; | |
1457 } | |
1458 if (dump_file) | 1511 if (dump_file) |
1459 { | 1512 fprintf (dump_file, |
1460 indent_to (dump_file, depth); | 1513 "Considering to always inline inline candidate %s.\n", |
1461 fprintf (dump_file, | 1514 cgraph_node_name (e->callee)); |
1462 "Considering to always inline inline candidate %s.\n", | |
1463 cgraph_node_name (e->callee)); | |
1464 } | |
1465 if (cgraph_recursive_inlining_p (node, e->callee, &e->inline_failed)) | 1515 if (cgraph_recursive_inlining_p (node, e->callee, &e->inline_failed)) |
1466 { | 1516 { |
1467 if (dump_file) | 1517 if (dump_file) |
1468 { | 1518 fprintf (dump_file, "Not inlining: recursive call.\n"); |
1469 indent_to (dump_file, depth); | |
1470 fprintf (dump_file, "Not inlining: recursive call.\n"); | |
1471 } | |
1472 continue; | 1519 continue; |
1473 } | 1520 } |
1474 if (!tree_can_inline_p (e)) | 1521 if (!tree_can_inline_p (e)) |
1475 { | 1522 { |
1476 if (dump_file) | 1523 if (dump_file) |
1477 { | 1524 fprintf (dump_file, |
1478 indent_to (dump_file, depth); | 1525 "Not inlining: %s", |
1479 fprintf (dump_file, | 1526 cgraph_inline_failed_string (e->inline_failed)); |
1480 "Not inlining: %s", | |
1481 cgraph_inline_failed_string (e->inline_failed)); | |
1482 } | |
1483 continue; | 1527 continue; |
1484 } | 1528 } |
1485 if (gimple_in_ssa_p (DECL_STRUCT_FUNCTION (node->decl)) | 1529 if (gimple_in_ssa_p (DECL_STRUCT_FUNCTION (node->decl)) |
1486 != gimple_in_ssa_p (DECL_STRUCT_FUNCTION (e->callee->decl))) | 1530 != gimple_in_ssa_p (DECL_STRUCT_FUNCTION (e->callee->decl))) |
1487 { | 1531 { |
1488 if (dump_file) | 1532 if (dump_file) |
1489 { | 1533 fprintf (dump_file, "Not inlining: SSA form does not match.\n"); |
1490 indent_to (dump_file, depth); | |
1491 fprintf (dump_file, "Not inlining: SSA form does not match.\n"); | |
1492 } | |
1493 continue; | 1534 continue; |
1494 } | 1535 } |
1495 if (!e->callee->analyzed) | 1536 if (!e->callee->analyzed) |
1496 { | 1537 { |
1497 if (dump_file) | 1538 if (dump_file) |
1498 { | 1539 fprintf (dump_file, |
1499 indent_to (dump_file, depth); | 1540 "Not inlining: Function body no longer available.\n"); |
1500 fprintf (dump_file, | |
1501 "Not inlining: Function body no longer available.\n"); | |
1502 } | |
1503 continue; | 1541 continue; |
1504 } | 1542 } |
1505 inlined |= try_inline (e, mode, depth); | 1543 |
1544 if (dump_file) | |
1545 fprintf (dump_file, " Inlining %s into %s.\n", | |
1546 cgraph_node_name (e->callee), | |
1547 cgraph_node_name (e->caller)); | |
1548 cgraph_mark_inline (e); | |
1549 inlined = true; | |
1506 } | 1550 } |
1507 | 1551 |
1508 /* Now do the automatic inlining. */ | 1552 /* Now do the automatic inlining. */ |
1509 if (mode != INLINE_ALL && mode != INLINE_ALWAYS_INLINE) | 1553 if (mode != INLINE_ALL && mode != INLINE_ALWAYS_INLINE |
1510 for (e = node->callees; e; e = e->next_callee) | 1554 /* Never inline regular functions into always-inline functions |
1511 { | 1555 during incremental inlining. */ |
1512 int allowed_growth = 0; | 1556 && !node->local.disregard_inline_limits) |
1513 if (!e->callee->local.inlinable | 1557 { |
1514 || !e->inline_failed | 1558 bitmap visited = BITMAP_ALLOC (NULL); |
1515 || e->callee->local.disregard_inline_limits) | 1559 for (e = node->callees; e; e = e->next_callee) |
1516 continue; | 1560 { |
1517 if (dump_file) | 1561 int allowed_growth = 0; |
1518 fprintf (dump_file, "Considering inline candidate %s.\n", | 1562 if (!e->callee->local.inlinable |
1519 cgraph_node_name (e->callee)); | 1563 || !e->inline_failed |
1520 if (cgraph_recursive_inlining_p (node, e->callee, &e->inline_failed)) | 1564 || e->callee->local.disregard_inline_limits) |
1521 { | 1565 continue; |
1522 if (dump_file) | 1566 /* We are inlining a function to all call-sites in node |
1523 { | 1567 or to none. So visit each candidate only once. */ |
1524 indent_to (dump_file, depth); | 1568 if (!bitmap_set_bit (visited, e->callee->uid)) |
1569 continue; | |
1570 if (dump_file) | |
1571 fprintf (dump_file, "Considering inline candidate %s.\n", | |
1572 cgraph_node_name (e->callee)); | |
1573 if (cgraph_recursive_inlining_p (node, e->callee, &e->inline_failed)) | |
1574 { | |
1575 if (dump_file) | |
1525 fprintf (dump_file, "Not inlining: recursive call.\n"); | 1576 fprintf (dump_file, "Not inlining: recursive call.\n"); |
1526 } | 1577 continue; |
1527 continue; | 1578 } |
1528 } | 1579 if (gimple_in_ssa_p (DECL_STRUCT_FUNCTION (node->decl)) |
1529 if (gimple_in_ssa_p (DECL_STRUCT_FUNCTION (node->decl)) | 1580 != gimple_in_ssa_p (DECL_STRUCT_FUNCTION (e->callee->decl))) |
1530 != gimple_in_ssa_p (DECL_STRUCT_FUNCTION (e->callee->decl))) | 1581 { |
1531 { | 1582 if (dump_file) |
1532 if (dump_file) | 1583 fprintf (dump_file, |
1533 { | 1584 "Not inlining: SSA form does not match.\n"); |
1534 indent_to (dump_file, depth); | 1585 continue; |
1535 fprintf (dump_file, "Not inlining: SSA form does not match.\n"); | 1586 } |
1536 } | 1587 |
1537 continue; | 1588 if (cgraph_maybe_hot_edge_p (e) && leaf_node_p (e->callee) |
1538 } | 1589 && optimize_function_for_speed_p (cfun)) |
1539 | 1590 allowed_growth = PARAM_VALUE (PARAM_EARLY_INLINING_INSNS); |
1540 if (cgraph_maybe_hot_edge_p (e) && leaf_node_p (e->callee) | 1591 |
1541 && optimize_function_for_speed_p (cfun)) | 1592 /* When the function body would grow and inlining the function |
1542 allowed_growth = PARAM_VALUE (PARAM_EARLY_INLINING_INSNS); | 1593 won't eliminate the need for offline copy of the function, |
1543 | 1594 don't inline. */ |
1544 /* When the function body would grow and inlining the function won't | 1595 if (((mode == INLINE_SIZE || mode == INLINE_SIZE_NORECURSIVE) |
1545 eliminate the need for offline copy of the function, don't inline. | 1596 || (!flag_inline_functions |
1546 */ | 1597 && !DECL_DECLARED_INLINE_P (e->callee->decl))) |
1547 if (((mode == INLINE_SIZE || mode == INLINE_SIZE_NORECURSIVE) | 1598 && (cgraph_estimate_size_after_inlining (1, e->caller, e->callee) |
1548 || (!flag_inline_functions | 1599 > e->caller->global.size + allowed_growth) |
1549 && !DECL_DECLARED_INLINE_P (e->callee->decl))) | 1600 && cgraph_estimate_growth (e->callee) > allowed_growth) |
1550 && (cgraph_estimate_size_after_inlining (1, e->caller, e->callee) | 1601 { |
1551 > e->caller->global.size + allowed_growth) | 1602 if (dump_file) |
1552 && cgraph_estimate_growth (e->callee) > allowed_growth) | |
1553 { | |
1554 if (dump_file) | |
1555 { | |
1556 indent_to (dump_file, depth); | |
1557 fprintf (dump_file, | 1603 fprintf (dump_file, |
1558 "Not inlining: code size would grow by %i.\n", | 1604 "Not inlining: code size would grow by %i.\n", |
1559 cgraph_estimate_size_after_inlining (1, e->caller, | 1605 cgraph_estimate_size_after_inlining (1, e->caller, |
1560 e->callee) | 1606 e->callee) |
1561 - e->caller->global.size); | 1607 - e->caller->global.size); |
1562 } | 1608 continue; |
1563 continue; | 1609 } |
1564 } | 1610 if (!cgraph_check_inline_limits (node, e->callee, &e->inline_failed, |
1565 if (!cgraph_check_inline_limits (node, e->callee, &e->inline_failed, | 1611 false) |
1566 false) | 1612 || e->call_stmt_cannot_inline_p) |
1567 || e->call_stmt_cannot_inline_p) | 1613 { |
1568 { | 1614 if (dump_file) |
1569 if (dump_file) | |
1570 { | |
1571 indent_to (dump_file, depth); | |
1572 fprintf (dump_file, "Not inlining: %s.\n", | 1615 fprintf (dump_file, "Not inlining: %s.\n", |
1573 cgraph_inline_failed_string (e->inline_failed)); | 1616 cgraph_inline_failed_string (e->inline_failed)); |
1574 } | 1617 continue; |
1575 continue; | 1618 } |
1576 } | 1619 if (!e->callee->analyzed) |
1577 if (!e->callee->analyzed) | 1620 { |
1578 { | 1621 if (dump_file) |
1579 if (dump_file) | |
1580 { | |
1581 indent_to (dump_file, depth); | |
1582 fprintf (dump_file, | 1622 fprintf (dump_file, |
1583 "Not inlining: Function body no longer available.\n"); | 1623 "Not inlining: Function body no longer available.\n"); |
1584 } | 1624 continue; |
1585 continue; | 1625 } |
1586 } | 1626 if (!tree_can_inline_p (e)) |
1587 if (!tree_can_inline_p (e)) | 1627 { |
1588 { | 1628 if (dump_file) |
1589 if (dump_file) | |
1590 { | |
1591 indent_to (dump_file, depth); | |
1592 fprintf (dump_file, | 1629 fprintf (dump_file, |
1593 "Not inlining: %s.", | 1630 "Not inlining: %s.", |
1594 cgraph_inline_failed_string (e->inline_failed)); | 1631 cgraph_inline_failed_string (e->inline_failed)); |
1595 } | 1632 continue; |
1596 continue; | 1633 } |
1597 } | 1634 if (cgraph_default_inline_p (e->callee, &failed_reason)) |
1598 if (cgraph_default_inline_p (e->callee, &failed_reason)) | 1635 { |
1599 inlined |= try_inline (e, mode, depth); | 1636 if (dump_file) |
1600 } | 1637 fprintf (dump_file, " Inlining %s into %s.\n", |
1601 node->aux = (void *)(size_t) old_mode; | 1638 cgraph_node_name (e->callee), |
1639 cgraph_node_name (e->caller)); | |
1640 cgraph_mark_inline (e); | |
1641 inlined = true; | |
1642 } | |
1643 } | |
1644 BITMAP_FREE (visited); | |
1645 } | |
1602 return inlined; | 1646 return inlined; |
1603 } | 1647 } |
1604 | 1648 |
1605 /* Because inlining might remove no-longer reachable nodes, we need to | 1649 /* Because inlining might remove no-longer reachable nodes, we need to |
1606 keep the array visible to garbage collector to avoid reading collected | 1650 keep the array visible to garbage collector to avoid reading collected |
1618 unsigned int todo = 0; | 1662 unsigned int todo = 0; |
1619 int iterations = 0; | 1663 int iterations = 0; |
1620 | 1664 |
1621 if (sorrycount || errorcount) | 1665 if (sorrycount || errorcount) |
1622 return 0; | 1666 return 0; |
1623 while (iterations < PARAM_VALUE (PARAM_EARLY_INLINER_MAX_ITERATIONS) | 1667 |
1624 && cgraph_decide_inlining_incrementally (node, | 1668 if (!optimize |
1625 iterations | 1669 || flag_no_inline |
1626 ? INLINE_SIZE_NORECURSIVE : INLINE_SIZE, 0)) | 1670 || !flag_early_inlining) |
1627 { | 1671 { |
1672 /* When not optimizing or not inlining inline only always-inline | |
1673 functions. */ | |
1674 cgraph_decide_inlining_incrementally (node, INLINE_ALWAYS_INLINE); | |
1628 timevar_push (TV_INTEGRATION); | 1675 timevar_push (TV_INTEGRATION); |
1629 todo |= optimize_inline_calls (current_function_decl); | 1676 todo |= optimize_inline_calls (current_function_decl); |
1630 iterations++; | |
1631 timevar_pop (TV_INTEGRATION); | 1677 timevar_pop (TV_INTEGRATION); |
1632 } | 1678 } |
1633 if (dump_file) | 1679 else |
1634 fprintf (dump_file, "Iterations: %i\n", iterations); | 1680 { |
1681 if (lookup_attribute ("flatten", | |
1682 DECL_ATTRIBUTES (node->decl)) != NULL) | |
1683 { | |
1684 if (dump_file) | |
1685 fprintf (dump_file, | |
1686 "Flattening %s\n", cgraph_node_name (node)); | |
1687 cgraph_flatten (node); | |
1688 timevar_push (TV_INTEGRATION); | |
1689 todo |= optimize_inline_calls (current_function_decl); | |
1690 timevar_pop (TV_INTEGRATION); | |
1691 } | |
1692 /* We iterate incremental inlining to get trivial cases of indirect | |
1693 inlining. */ | |
1694 while (iterations < PARAM_VALUE (PARAM_EARLY_INLINER_MAX_ITERATIONS) | |
1695 && cgraph_decide_inlining_incrementally (node, | |
1696 iterations | |
1697 ? INLINE_SIZE_NORECURSIVE | |
1698 : INLINE_SIZE)) | |
1699 { | |
1700 timevar_push (TV_INTEGRATION); | |
1701 todo |= optimize_inline_calls (current_function_decl); | |
1702 iterations++; | |
1703 timevar_pop (TV_INTEGRATION); | |
1704 } | |
1705 if (dump_file) | |
1706 fprintf (dump_file, "Iterations: %i\n", iterations); | |
1707 } | |
1708 | |
1635 cfun->always_inline_functions_inlined = true; | 1709 cfun->always_inline_functions_inlined = true; |
1710 | |
1636 return todo; | 1711 return todo; |
1637 } | |
1638 | |
1639 /* When inlining shall be performed. */ | |
1640 static bool | |
1641 cgraph_gate_early_inlining (void) | |
1642 { | |
1643 return flag_early_inlining; | |
1644 } | 1712 } |
1645 | 1713 |
1646 struct gimple_opt_pass pass_early_inline = | 1714 struct gimple_opt_pass pass_early_inline = |
1647 { | 1715 { |
1648 { | 1716 { |
1649 GIMPLE_PASS, | 1717 GIMPLE_PASS, |
1650 "einline", /* name */ | 1718 "einline", /* name */ |
1651 cgraph_gate_early_inlining, /* gate */ | 1719 NULL, /* gate */ |
1652 cgraph_early_inlining, /* execute */ | 1720 cgraph_early_inlining, /* execute */ |
1653 NULL, /* sub */ | 1721 NULL, /* sub */ |
1654 NULL, /* next */ | 1722 NULL, /* next */ |
1655 0, /* static_pass_number */ | 1723 0, /* static_pass_number */ |
1656 TV_INLINE_HEURISTICS, /* tv_id */ | 1724 TV_INLINE_HEURISTICS, /* tv_id */ |
1857 inline_summary (node)->estimated_self_stack_size = self_stack_size; | 1925 inline_summary (node)->estimated_self_stack_size = self_stack_size; |
1858 node->global.estimated_stack_size = self_stack_size; | 1926 node->global.estimated_stack_size = self_stack_size; |
1859 node->global.stack_frame_offset = 0; | 1927 node->global.stack_frame_offset = 0; |
1860 | 1928 |
1861 /* Can this function be inlined at all? */ | 1929 /* Can this function be inlined at all? */ |
1862 node->local.inlinable = tree_inlinable_function_p (current_function_decl); | 1930 node->local.inlinable = tree_inlinable_function_p (node->decl); |
1863 if (node->local.inlinable && !node->local.disregard_inline_limits) | 1931 if (node->local.inlinable && !node->local.disregard_inline_limits) |
1864 node->local.disregard_inline_limits | 1932 node->local.disregard_inline_limits |
1865 = DECL_DISREGARD_INLINE_LIMITS (current_function_decl); | 1933 = DECL_DISREGARD_INLINE_LIMITS (node->decl); |
1866 estimate_function_body_sizes (node); | 1934 estimate_function_body_sizes (node); |
1867 /* Inlining characteristics are maintained by the cgraph_mark_inline. */ | 1935 /* Inlining characteristics are maintained by the cgraph_mark_inline. */ |
1868 node->global.time = inline_summary (node)->self_time; | 1936 node->global.time = inline_summary (node)->self_time; |
1869 node->global.size = inline_summary (node)->self_size; | 1937 node->global.size = inline_summary (node)->self_size; |
1870 return 0; | 1938 return 0; |
1902 /* This function performs intraprocedural analyzis in NODE that is required to | 1970 /* This function performs intraprocedural analyzis in NODE that is required to |
1903 inline indirect calls. */ | 1971 inline indirect calls. */ |
1904 static void | 1972 static void |
1905 inline_indirect_intraprocedural_analysis (struct cgraph_node *node) | 1973 inline_indirect_intraprocedural_analysis (struct cgraph_node *node) |
1906 { | 1974 { |
1907 struct cgraph_edge *cs; | 1975 ipa_initialize_node_params (node); |
1908 | 1976 ipa_detect_param_modifications (node); |
1909 if (!flag_ipa_cp) | |
1910 { | |
1911 ipa_initialize_node_params (node); | |
1912 ipa_detect_param_modifications (node); | |
1913 } | |
1914 ipa_analyze_params_uses (node); | 1977 ipa_analyze_params_uses (node); |
1915 | 1978 ipa_compute_jump_functions (node); |
1916 if (!flag_ipa_cp) | |
1917 for (cs = node->callees; cs; cs = cs->next_callee) | |
1918 { | |
1919 ipa_count_arguments (cs); | |
1920 ipa_compute_jump_functions (cs); | |
1921 } | |
1922 | 1979 |
1923 if (dump_file) | 1980 if (dump_file) |
1924 { | 1981 { |
1925 ipa_print_node_params (dump_file, node); | 1982 ipa_print_node_params (dump_file, node); |
1926 ipa_print_node_jump_functions (dump_file, node); | 1983 ipa_print_node_jump_functions (dump_file, node); |
2024 /* Write inline summary for node in SET. | 2081 /* Write inline summary for node in SET. |
2025 Jump functions are shared among ipa-cp and inliner, so when ipa-cp is | 2082 Jump functions are shared among ipa-cp and inliner, so when ipa-cp is |
2026 active, we don't need to write them twice. */ | 2083 active, we don't need to write them twice. */ |
2027 | 2084 |
2028 static void | 2085 static void |
2029 inline_write_summary (cgraph_node_set set) | 2086 inline_write_summary (cgraph_node_set set, |
2087 varpool_node_set vset ATTRIBUTE_UNUSED) | |
2030 { | 2088 { |
2031 if (flag_indirect_inlining && !flag_ipa_cp) | 2089 if (flag_indirect_inlining && !flag_ipa_cp) |
2032 ipa_prop_write_jump_functions (set); | 2090 ipa_prop_write_jump_functions (set); |
2091 } | |
2092 | |
2093 /* When to run IPA inlining. Inlining of always-inline functions | |
2094 happens during early inlining. */ | |
2095 | |
2096 static bool | |
2097 gate_cgraph_decide_inlining (void) | |
2098 { | |
2099 /* ??? We'd like to skip this if not optimizing or not inlining as | |
2100 all always-inline functions have been processed by early | |
2101 inlining already. But this at least breaks EH with C++ as | |
2102 we need to unconditionally run fixup_cfg even at -O0. | |
2103 So leave it on unconditionally for now. */ | |
2104 return 1; | |
2033 } | 2105 } |
2034 | 2106 |
2035 struct ipa_opt_pass_d pass_ipa_inline = | 2107 struct ipa_opt_pass_d pass_ipa_inline = |
2036 { | 2108 { |
2037 { | 2109 { |
2038 IPA_PASS, | 2110 IPA_PASS, |
2039 "inline", /* name */ | 2111 "inline", /* name */ |
2040 NULL, /* gate */ | 2112 gate_cgraph_decide_inlining, /* gate */ |
2041 cgraph_decide_inlining, /* execute */ | 2113 cgraph_decide_inlining, /* execute */ |
2042 NULL, /* sub */ | 2114 NULL, /* sub */ |
2043 NULL, /* next */ | 2115 NULL, /* next */ |
2044 0, /* static_pass_number */ | 2116 0, /* static_pass_number */ |
2045 TV_INLINE_HEURISTICS, /* tv_id */ | 2117 TV_INLINE_HEURISTICS, /* tv_id */ |
2046 0, /* properties_required */ | 2118 0, /* properties_required */ |
2047 0, /* properties_provided */ | 2119 0, /* properties_provided */ |
2048 0, /* properties_destroyed */ | 2120 0, /* properties_destroyed */ |
2049 TODO_remove_functions, /* todo_flags_finish */ | 2121 TODO_remove_functions, /* todo_flags_finish */ |
2050 TODO_dump_cgraph | TODO_dump_func | 2122 TODO_dump_cgraph | TODO_dump_func |
2051 | TODO_remove_functions /* todo_flags_finish */ | 2123 | TODO_remove_functions | TODO_ggc_collect /* todo_flags_finish */ |
2052 }, | 2124 }, |
2053 inline_generate_summary, /* generate_summary */ | 2125 inline_generate_summary, /* generate_summary */ |
2054 inline_write_summary, /* write_summary */ | 2126 inline_write_summary, /* write_summary */ |
2055 inline_read_summary, /* read_summary */ | 2127 inline_read_summary, /* read_summary */ |
2056 NULL, /* function_read_summary */ | 2128 NULL, /* write_optimization_summary */ |
2057 lto_ipa_fixup_call_notes, /* stmt_fixup */ | 2129 NULL, /* read_optimization_summary */ |
2130 NULL, /* stmt_fixup */ | |
2058 0, /* TODOs */ | 2131 0, /* TODOs */ |
2059 inline_transform, /* function_transform */ | 2132 inline_transform, /* function_transform */ |
2060 NULL, /* variable_transform */ | 2133 NULL, /* variable_transform */ |
2061 }; | 2134 }; |
2062 | 2135 |