Mercurial > hg > CbC > CbC_gcc
comparison gcc/ipa-inline-transform.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
1 /* Callgraph transformations to handle inlining | 1 /* Callgraph transformations to handle inlining |
2 Copyright (C) 2003-2017 Free Software Foundation, Inc. | 2 Copyright (C) 2003-2018 Free Software Foundation, Inc. |
3 Contributed by Jan Hubicka | 3 Contributed by Jan Hubicka |
4 | 4 |
5 This file is part of GCC. | 5 This file is part of GCC. |
6 | 6 |
7 GCC is free software; you can redistribute it and/or modify it under | 7 GCC is free software; you can redistribute it and/or modify it under |
49 #include "basic-block.h" | 49 #include "basic-block.h" |
50 | 50 |
51 int ncalls_inlined; | 51 int ncalls_inlined; |
52 int nfunctions_inlined; | 52 int nfunctions_inlined; |
53 | 53 |
54 /* Scale frequency of NODE edges by FREQ_SCALE. */ | 54 /* Scale counts of NODE edges by NUM/DEN. */ |
55 | 55 |
56 static void | 56 static void |
57 update_noncloned_frequencies (struct cgraph_node *node, | 57 update_noncloned_counts (struct cgraph_node *node, |
58 int freq_scale, profile_count num, | 58 profile_count num, profile_count den) |
59 profile_count den) | |
60 { | 59 { |
61 struct cgraph_edge *e; | 60 struct cgraph_edge *e; |
62 bool scale = (num == profile_count::zero () || den > 0); | 61 |
63 | 62 profile_count::adjust_for_ipa_scaling (&num, &den); |
64 /* We do not want to ignore high loop nest after freq drops to 0. */ | 63 |
65 if (!freq_scale) | |
66 freq_scale = 1; | |
67 for (e = node->callees; e; e = e->next_callee) | 64 for (e = node->callees; e; e = e->next_callee) |
68 { | 65 { |
69 e->frequency = e->frequency * (gcov_type) freq_scale / CGRAPH_FREQ_BASE; | |
70 if (e->frequency > CGRAPH_FREQ_MAX) | |
71 e->frequency = CGRAPH_FREQ_MAX; | |
72 if (!e->inline_failed) | 66 if (!e->inline_failed) |
73 update_noncloned_frequencies (e->callee, freq_scale, num, den); | 67 update_noncloned_counts (e->callee, num, den); |
74 if (scale) | 68 e->count = e->count.apply_scale (num, den); |
75 e->count = e->count.apply_scale (num, den); | |
76 } | 69 } |
77 for (e = node->indirect_calls; e; e = e->next_callee) | 70 for (e = node->indirect_calls; e; e = e->next_callee) |
78 { | 71 e->count = e->count.apply_scale (num, den); |
79 e->frequency = e->frequency * (gcov_type) freq_scale / CGRAPH_FREQ_BASE; | 72 node->count = node->count.apply_scale (num, den); |
80 if (e->frequency > CGRAPH_FREQ_MAX) | |
81 e->frequency = CGRAPH_FREQ_MAX; | |
82 if (scale) | |
83 e->count = e->count.apply_scale (num, den); | |
84 } | |
85 if (scale) | |
86 node->count = node->count.apply_scale (num, den); | |
87 } | 73 } |
88 | 74 |
89 /* We removed or are going to remove the last call to NODE. | 75 /* We removed or are going to remove the last call to NODE. |
90 Return true if we can and want proactively remove the NODE now. | 76 Return true if we can and want proactively remove the NODE now. |
91 This is important to do, since we want inliner to know when offline | 77 This is important to do, since we want inliner to know when offline |
169 DUPLICATE is used for bookkeeping on whether we are actually creating new | 155 DUPLICATE is used for bookkeeping on whether we are actually creating new |
170 clones or re-using node originally representing out-of-line function call. | 156 clones or re-using node originally representing out-of-line function call. |
171 By default the offline copy is removed, when it appears dead after inlining. | 157 By default the offline copy is removed, when it appears dead after inlining. |
172 UPDATE_ORIGINAL prevents this transformation. | 158 UPDATE_ORIGINAL prevents this transformation. |
173 If OVERALL_SIZE is non-NULL, the size is updated to reflect the | 159 If OVERALL_SIZE is non-NULL, the size is updated to reflect the |
174 transformation. | 160 transformation. */ |
175 FREQ_SCALE specify the scaling of frequencies of call sites. */ | |
176 | 161 |
177 void | 162 void |
178 clone_inlined_nodes (struct cgraph_edge *e, bool duplicate, | 163 clone_inlined_nodes (struct cgraph_edge *e, bool duplicate, |
179 bool update_original, int *overall_size, int freq_scale) | 164 bool update_original, int *overall_size) |
180 { | 165 { |
181 struct cgraph_node *inlining_into; | 166 struct cgraph_node *inlining_into; |
182 struct cgraph_edge *next; | 167 struct cgraph_edge *next; |
183 | 168 |
184 if (e->caller->global.inlined_to) | 169 if (e->caller->global.inlined_to) |
213 if (e->callee->definition | 198 if (e->callee->definition |
214 && inline_account_function_p (e->callee)) | 199 && inline_account_function_p (e->callee)) |
215 { | 200 { |
216 gcc_assert (!e->callee->alias); | 201 gcc_assert (!e->callee->alias); |
217 if (overall_size) | 202 if (overall_size) |
218 *overall_size -= ipa_fn_summaries->get (e->callee)->size; | 203 *overall_size -= ipa_fn_summaries->get (e->callee)->size; |
219 nfunctions_inlined++; | 204 nfunctions_inlined++; |
220 } | 205 } |
221 duplicate = false; | 206 duplicate = false; |
222 e->callee->externally_visible = false; | 207 e->callee->externally_visible = false; |
223 update_noncloned_frequencies (e->callee, e->frequency, | 208 update_noncloned_counts (e->callee, e->count, e->callee->count); |
224 e->count, e->callee->count); | |
225 | 209 |
226 dump_callgraph_transformation (e->callee, inlining_into, | 210 dump_callgraph_transformation (e->callee, inlining_into, |
227 "inlining to"); | 211 "inlining to"); |
228 } | 212 } |
229 else | 213 else |
230 { | 214 { |
231 struct cgraph_node *n; | 215 struct cgraph_node *n; |
232 | 216 |
233 if (freq_scale == -1) | |
234 freq_scale = e->frequency; | |
235 n = e->callee->create_clone (e->callee->decl, | 217 n = e->callee->create_clone (e->callee->decl, |
236 MIN (e->count, e->callee->count), | 218 e->count, |
237 freq_scale, | |
238 update_original, vNULL, true, | 219 update_original, vNULL, true, |
239 inlining_into, | 220 inlining_into, |
240 NULL); | 221 NULL); |
241 n->used_as_abstract_origin = e->callee->used_as_abstract_origin; | 222 n->used_as_abstract_origin = e->callee->used_as_abstract_origin; |
242 e->redirect_callee (n); | 223 e->redirect_callee (n); |
250 /* Recursively clone all bodies. */ | 231 /* Recursively clone all bodies. */ |
251 for (e = e->callee->callees; e; e = next) | 232 for (e = e->callee->callees; e; e = next) |
252 { | 233 { |
253 next = e->next_callee; | 234 next = e->next_callee; |
254 if (!e->inline_failed) | 235 if (!e->inline_failed) |
255 clone_inlined_nodes (e, duplicate, update_original, overall_size, freq_scale); | 236 clone_inlined_nodes (e, duplicate, update_original, overall_size); |
256 } | 237 } |
257 } | 238 } |
258 | 239 |
259 /* Check all speculations in N and resolve them if they seems useless. */ | 240 /* Check all speculations in N and resolve them if they seems useless. */ |
260 | 241 |
457 else | 438 else |
458 break; | 439 break; |
459 } | 440 } |
460 } | 441 } |
461 | 442 |
462 clone_inlined_nodes (e, true, update_original, overall_size, e->frequency); | 443 clone_inlined_nodes (e, true, update_original, overall_size); |
463 | 444 |
464 gcc_assert (curr->callee->global.inlined_to == to); | 445 gcc_assert (curr->callee->global.inlined_to == to); |
465 | 446 |
466 old_size = ipa_fn_summaries->get (to)->size; | 447 old_size = ipa_fn_summaries->get (to)->size; |
467 ipa_merge_fn_summary_after_inlining (e); | 448 ipa_merge_fn_summary_after_inlining (e); |
674 timevar_push (TV_INTEGRATION); | 655 timevar_push (TV_INTEGRATION); |
675 if (node->callees && (opt_for_fn (node->decl, optimize) || has_inline)) | 656 if (node->callees && (opt_for_fn (node->decl, optimize) || has_inline)) |
676 { | 657 { |
677 profile_count num = node->count; | 658 profile_count num = node->count; |
678 profile_count den = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count; | 659 profile_count den = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count; |
679 bool scale = num.initialized_p () | 660 bool scale = num.initialized_p () && !(num == den); |
680 && (den > 0 || num == profile_count::zero ()) | |
681 && !(num == den); | |
682 if (scale) | 661 if (scale) |
683 { | 662 { |
663 profile_count::adjust_for_ipa_scaling (&num, &den); | |
684 if (dump_file) | 664 if (dump_file) |
685 { | 665 { |
686 fprintf (dump_file, "Applying count scale "); | 666 fprintf (dump_file, "Applying count scale "); |
687 num.dump (dump_file); | 667 num.dump (dump_file); |
688 fprintf (dump_file, "/"); | 668 fprintf (dump_file, "/"); |
689 den.dump (dump_file); | 669 den.dump (dump_file); |
690 fprintf (dump_file, "\n"); | 670 fprintf (dump_file, "\n"); |
691 } | 671 } |
692 | 672 |
693 basic_block bb; | 673 basic_block bb; |
674 cfun->cfg->count_max = profile_count::uninitialized (); | |
694 FOR_ALL_BB_FN (bb, cfun) | 675 FOR_ALL_BB_FN (bb, cfun) |
695 bb->count = bb->count.apply_scale (num, den); | 676 { |
677 bb->count = bb->count.apply_scale (num, den); | |
678 cfun->cfg->count_max = cfun->cfg->count_max.max (bb->count); | |
679 } | |
696 ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = node->count; | 680 ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = node->count; |
697 } | 681 } |
698 todo = optimize_inline_calls (current_function_decl); | 682 todo = optimize_inline_calls (current_function_decl); |
699 } | 683 } |
700 timevar_pop (TV_INTEGRATION); | 684 timevar_pop (TV_INTEGRATION); |