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);