Mercurial > hg > CbC > CbC_gcc
comparison gcc/cgraphclones.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 clones | 1 /* Callgraph clones |
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 |
85 the callgraph. */ | 85 the callgraph. */ |
86 | 86 |
87 cgraph_edge * | 87 cgraph_edge * |
88 cgraph_edge::clone (cgraph_node *n, gcall *call_stmt, unsigned stmt_uid, | 88 cgraph_edge::clone (cgraph_node *n, gcall *call_stmt, unsigned stmt_uid, |
89 profile_count num, profile_count den, | 89 profile_count num, profile_count den, |
90 int freq_scale, bool update_original) | 90 bool update_original) |
91 { | 91 { |
92 cgraph_edge *new_edge; | 92 cgraph_edge *new_edge; |
93 profile_count gcov_count | 93 profile_count::adjust_for_ipa_scaling (&num, &den); |
94 = (num == profile_count::zero () || den > 0) | 94 profile_count prof_count = count.apply_scale (num, den); |
95 ? count.apply_scale (num, den) : count; | |
96 gcov_type freq; | |
97 | |
98 /* We do not want to ignore loop nest after frequency drops to 0. */ | |
99 if (!freq_scale) | |
100 freq_scale = 1; | |
101 freq = frequency * (gcov_type) freq_scale / CGRAPH_FREQ_BASE; | |
102 if (freq > CGRAPH_FREQ_MAX) | |
103 freq = CGRAPH_FREQ_MAX; | |
104 | 95 |
105 if (indirect_unknown_callee) | 96 if (indirect_unknown_callee) |
106 { | 97 { |
107 tree decl; | 98 tree decl; |
108 | 99 |
111 via cgraph_resolve_speculation and not here. */ | 102 via cgraph_resolve_speculation and not here. */ |
112 && !speculative) | 103 && !speculative) |
113 { | 104 { |
114 cgraph_node *callee = cgraph_node::get (decl); | 105 cgraph_node *callee = cgraph_node::get (decl); |
115 gcc_checking_assert (callee); | 106 gcc_checking_assert (callee); |
116 new_edge = n->create_edge (callee, call_stmt, gcov_count, freq); | 107 new_edge = n->create_edge (callee, call_stmt, prof_count); |
117 } | 108 } |
118 else | 109 else |
119 { | 110 { |
120 new_edge = n->create_indirect_edge (call_stmt, | 111 new_edge = n->create_indirect_edge (call_stmt, |
121 indirect_info->ecf_flags, | 112 indirect_info->ecf_flags, |
122 gcov_count, freq, false); | 113 prof_count, false); |
123 *new_edge->indirect_info = *indirect_info; | 114 *new_edge->indirect_info = *indirect_info; |
124 } | 115 } |
125 } | 116 } |
126 else | 117 else |
127 { | 118 { |
128 new_edge = n->create_edge (callee, call_stmt, gcov_count, freq); | 119 new_edge = n->create_edge (callee, call_stmt, prof_count); |
129 if (indirect_info) | 120 if (indirect_info) |
130 { | 121 { |
131 new_edge->indirect_info | 122 new_edge->indirect_info |
132 = ggc_cleared_alloc<cgraph_indirect_call_info> (); | 123 = ggc_cleared_alloc<cgraph_indirect_call_info> (); |
133 *new_edge->indirect_info = *indirect_info; | 124 *new_edge->indirect_info = *indirect_info; |
140 /* Clone flags that depend on call_stmt availability manually. */ | 131 /* Clone flags that depend on call_stmt availability manually. */ |
141 new_edge->can_throw_external = can_throw_external; | 132 new_edge->can_throw_external = can_throw_external; |
142 new_edge->call_stmt_cannot_inline_p = call_stmt_cannot_inline_p; | 133 new_edge->call_stmt_cannot_inline_p = call_stmt_cannot_inline_p; |
143 new_edge->speculative = speculative; | 134 new_edge->speculative = speculative; |
144 new_edge->in_polymorphic_cdtor = in_polymorphic_cdtor; | 135 new_edge->in_polymorphic_cdtor = in_polymorphic_cdtor; |
136 | |
137 /* Update IPA profile. Local profiles need no updating in original. */ | |
145 if (update_original) | 138 if (update_original) |
146 { | 139 count = count.combine_with_ipa_count (count.ipa () |
147 count -= new_edge->count; | 140 - new_edge->count.ipa ()); |
148 } | |
149 symtab->call_edge_duplication_hooks (this, new_edge); | 141 symtab->call_edge_duplication_hooks (this, new_edge); |
150 return new_edge; | 142 return new_edge; |
151 } | 143 } |
152 | 144 |
153 /* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP and the | 145 /* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP and the |
228 we expect first argument to be THIS pointer. */ | 220 we expect first argument to be THIS pointer. */ |
229 if (args_to_skip && bitmap_bit_p (args_to_skip, 0)) | 221 if (args_to_skip && bitmap_bit_p (args_to_skip, 0)) |
230 DECL_VINDEX (new_decl) = NULL_TREE; | 222 DECL_VINDEX (new_decl) = NULL_TREE; |
231 | 223 |
232 /* When signature changes, we need to clear builtin info. */ | 224 /* When signature changes, we need to clear builtin info. */ |
233 if (DECL_BUILT_IN (new_decl) | 225 if (fndecl_built_in_p (new_decl) |
234 && args_to_skip | 226 && args_to_skip |
235 && !bitmap_empty_p (args_to_skip)) | 227 && !bitmap_empty_p (args_to_skip)) |
236 { | 228 { |
237 DECL_BUILT_IN_CLASS (new_decl) = NOT_BUILT_IN; | 229 DECL_BUILT_IN_CLASS (new_decl) = NOT_BUILT_IN; |
238 DECL_FUNCTION_CODE (new_decl) = (enum built_in_function) 0; | 230 DECL_FUNCTION_CODE (new_decl) = (enum built_in_function) 0; |
280 thunk->get_untransformed_body (); | 272 thunk->get_untransformed_body (); |
281 | 273 |
282 cgraph_edge *cs; | 274 cgraph_edge *cs; |
283 for (cs = node->callers; cs; cs = cs->next_caller) | 275 for (cs = node->callers; cs; cs = cs->next_caller) |
284 if (cs->caller->thunk.thunk_p | 276 if (cs->caller->thunk.thunk_p |
277 && cs->caller->thunk.fixed_offset == thunk->thunk.fixed_offset | |
278 && cs->caller->thunk.virtual_value == thunk->thunk.virtual_value | |
279 && cs->caller->thunk.indirect_offset == thunk->thunk.indirect_offset | |
285 && cs->caller->thunk.this_adjusting == thunk->thunk.this_adjusting | 280 && cs->caller->thunk.this_adjusting == thunk->thunk.this_adjusting |
286 && cs->caller->thunk.fixed_offset == thunk->thunk.fixed_offset | 281 && cs->caller->thunk.virtual_offset_p == thunk->thunk.virtual_offset_p) |
287 && cs->caller->thunk.virtual_offset_p == thunk->thunk.virtual_offset_p | |
288 && cs->caller->thunk.virtual_value == thunk->thunk.virtual_value) | |
289 return cs->caller; | 282 return cs->caller; |
290 | 283 |
291 tree new_decl; | 284 tree new_decl; |
292 if (!node->clone.args_to_skip) | 285 if (!node->clone.args_to_skip) |
293 new_decl = copy_node (thunk->decl); | 286 new_decl = copy_node (thunk->decl); |
335 new_thunk->unique_name = in_lto_p; | 328 new_thunk->unique_name = in_lto_p; |
336 new_thunk->former_clone_of = thunk->decl; | 329 new_thunk->former_clone_of = thunk->decl; |
337 new_thunk->clone.args_to_skip = node->clone.args_to_skip; | 330 new_thunk->clone.args_to_skip = node->clone.args_to_skip; |
338 new_thunk->clone.combined_args_to_skip = node->clone.combined_args_to_skip; | 331 new_thunk->clone.combined_args_to_skip = node->clone.combined_args_to_skip; |
339 | 332 |
340 cgraph_edge *e = new_thunk->create_edge (node, NULL, new_thunk->count, | 333 cgraph_edge *e = new_thunk->create_edge (node, NULL, new_thunk->count); |
341 CGRAPH_FREQ_BASE); | |
342 symtab->call_edge_duplication_hooks (thunk->callees, e); | 334 symtab->call_edge_duplication_hooks (thunk->callees, e); |
343 symtab->call_cgraph_duplication_hooks (thunk, new_thunk); | 335 symtab->call_cgraph_duplication_hooks (thunk, new_thunk); |
344 return new_thunk; | 336 return new_thunk; |
345 } | 337 } |
346 | 338 |
420 the outline function the new one is (even indirectly) inlined to. All hooks | 412 the outline function the new one is (even indirectly) inlined to. All hooks |
421 will see this in node's global.inlined_to, when invoked. Can be NULL if the | 413 will see this in node's global.inlined_to, when invoked. Can be NULL if the |
422 node is not inlined. */ | 414 node is not inlined. */ |
423 | 415 |
424 cgraph_node * | 416 cgraph_node * |
425 cgraph_node::create_clone (tree new_decl, profile_count prof_count, int freq, | 417 cgraph_node::create_clone (tree new_decl, profile_count prof_count, |
426 bool update_original, | 418 bool update_original, |
427 vec<cgraph_edge *> redirect_callers, | 419 vec<cgraph_edge *> redirect_callers, |
428 bool call_duplication_hook, | 420 bool call_duplication_hook, |
429 cgraph_node *new_inlined_to, | 421 cgraph_node *new_inlined_to, |
430 bitmap args_to_skip, const char *suffix) | 422 bitmap args_to_skip, const char *suffix) |
431 { | 423 { |
432 cgraph_node *new_node = symtab->create_empty (); | 424 cgraph_node *new_node = symtab->create_empty (); |
433 cgraph_edge *e; | 425 cgraph_edge *e; |
434 unsigned i; | 426 unsigned i; |
427 profile_count old_count = count; | |
435 | 428 |
436 if (new_inlined_to) | 429 if (new_inlined_to) |
437 dump_callgraph_transformation (this, new_inlined_to, "inlining to"); | 430 dump_callgraph_transformation (this, new_inlined_to, "inlining to"); |
438 | 431 |
432 /* When inlining we scale precisely to prof_count, when cloning we can | |
433 preserve local profile. */ | |
434 if (!new_inlined_to) | |
435 prof_count = count.combine_with_ipa_count (prof_count); | |
439 new_node->count = prof_count; | 436 new_node->count = prof_count; |
437 | |
438 /* Update IPA profile. Local profiles need no updating in original. */ | |
439 if (update_original) | |
440 count = count.combine_with_ipa_count (count.ipa () - prof_count.ipa ()); | |
440 new_node->decl = new_decl; | 441 new_node->decl = new_decl; |
441 new_node->register_symbol (); | 442 new_node->register_symbol (); |
442 new_node->origin = origin; | 443 new_node->origin = origin; |
443 new_node->lto_file_data = lto_file_data; | 444 new_node->lto_file_data = lto_file_data; |
444 if (new_node->origin) | 445 if (new_node->origin) |
480 { | 481 { |
481 /* Redirect calls to the old version node to point to its new | 482 /* Redirect calls to the old version node to point to its new |
482 version. The only exception is when the edge was proved to | 483 version. The only exception is when the edge was proved to |
483 be unreachable during the clonning procedure. */ | 484 be unreachable during the clonning procedure. */ |
484 if (!e->callee | 485 if (!e->callee |
485 || DECL_BUILT_IN_CLASS (e->callee->decl) != BUILT_IN_NORMAL | 486 || !fndecl_built_in_p (e->callee->decl, BUILT_IN_UNREACHABLE)) |
486 || DECL_FUNCTION_CODE (e->callee->decl) != BUILT_IN_UNREACHABLE) | |
487 e->redirect_callee_duplicating_thunks (new_node); | 487 e->redirect_callee_duplicating_thunks (new_node); |
488 } | 488 } |
489 new_node->expand_all_artificial_thunks (); | 489 new_node->expand_all_artificial_thunks (); |
490 | 490 |
491 for (e = callees;e; e=e->next_callee) | 491 for (e = callees;e; e=e->next_callee) |
492 e->clone (new_node, e->call_stmt, e->lto_stmt_uid, new_node->count, count, | 492 e->clone (new_node, e->call_stmt, e->lto_stmt_uid, new_node->count, old_count, |
493 freq, update_original); | 493 update_original); |
494 | 494 |
495 for (e = indirect_calls; e; e = e->next_callee) | 495 for (e = indirect_calls; e; e = e->next_callee) |
496 e->clone (new_node, e->call_stmt, e->lto_stmt_uid, | 496 e->clone (new_node, e->call_stmt, e->lto_stmt_uid, |
497 new_node->count, count, freq, update_original); | 497 new_node->count, old_count, update_original); |
498 new_node->clone_references (this); | 498 new_node->clone_references (this); |
499 | 499 |
500 new_node->next_sibling_clone = clones; | 500 new_node->next_sibling_clone = clones; |
501 if (clones) | 501 if (clones) |
502 clones->prev_sibling_clone = new_node; | 502 clones->prev_sibling_clone = new_node; |
503 clones = new_node; | 503 clones = new_node; |
504 new_node->clone_of = this; | 504 new_node->clone_of = this; |
505 | |
506 if (update_original) | |
507 count -= prof_count; | |
508 | 505 |
509 if (call_duplication_hook) | 506 if (call_duplication_hook) |
510 symtab->call_cgraph_duplication_hooks (this, new_node); | 507 symtab->call_cgraph_duplication_hooks (this, new_node); |
511 | 508 |
512 if (!new_inlined_to) | 509 if (!new_inlined_to) |
589 name[len] = '.'; | 586 name[len] = '.'; |
590 DECL_NAME (new_decl) = get_identifier (name); | 587 DECL_NAME (new_decl) = get_identifier (name); |
591 SET_DECL_ASSEMBLER_NAME (new_decl, clone_function_name (old_decl, suffix)); | 588 SET_DECL_ASSEMBLER_NAME (new_decl, clone_function_name (old_decl, suffix)); |
592 SET_DECL_RTL (new_decl, NULL); | 589 SET_DECL_RTL (new_decl, NULL); |
593 | 590 |
594 new_node = create_clone (new_decl, count, CGRAPH_FREQ_BASE, false, | 591 new_node = create_clone (new_decl, count, false, |
595 redirect_callers, false, NULL, args_to_skip, suffix); | 592 redirect_callers, false, NULL, args_to_skip, suffix); |
596 | 593 |
597 /* Update the properties. | 594 /* Update the properties. |
598 Make clone visible only within this translation unit. Make sure | 595 Make clone visible only within this translation unit. Make sure |
599 that is not weak also. | 596 that is not weak also. |
771 | 768 |
772 void | 769 void |
773 cgraph_node::create_edge_including_clones (cgraph_node *callee, | 770 cgraph_node::create_edge_including_clones (cgraph_node *callee, |
774 gimple *old_stmt, gcall *stmt, | 771 gimple *old_stmt, gcall *stmt, |
775 profile_count count, | 772 profile_count count, |
776 int freq, | |
777 cgraph_inline_failed_t reason) | 773 cgraph_inline_failed_t reason) |
778 { | 774 { |
779 cgraph_node *node; | 775 cgraph_node *node; |
780 cgraph_edge *edge; | 776 cgraph_edge *edge; |
781 | 777 |
782 if (!get_edge (stmt)) | 778 if (!get_edge (stmt)) |
783 { | 779 { |
784 edge = create_edge (callee, stmt, count, freq); | 780 edge = create_edge (callee, stmt, count); |
785 edge->inline_failed = reason; | 781 edge->inline_failed = reason; |
786 } | 782 } |
787 | 783 |
788 node = clones; | 784 node = clones; |
789 if (node) | 785 if (node) |
799 master where edges has been removed. */ | 795 master where edges has been removed. */ |
800 if (edge) | 796 if (edge) |
801 edge->set_call_stmt (stmt); | 797 edge->set_call_stmt (stmt); |
802 else if (! node->get_edge (stmt)) | 798 else if (! node->get_edge (stmt)) |
803 { | 799 { |
804 edge = node->create_edge (callee, stmt, count, freq); | 800 edge = node->create_edge (callee, stmt, count); |
805 edge->inline_failed = reason; | 801 edge->inline_failed = reason; |
806 } | 802 } |
807 | 803 |
808 if (node->clones) | 804 if (node->clones) |
809 node = node->clones; | 805 node = node->clones; |
902 for (e = callees; e; e=e->next_callee) | 898 for (e = callees; e; e=e->next_callee) |
903 if (!bbs_to_copy | 899 if (!bbs_to_copy |
904 || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index)) | 900 || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index)) |
905 e->clone (new_version, e->call_stmt, | 901 e->clone (new_version, e->call_stmt, |
906 e->lto_stmt_uid, count, count, | 902 e->lto_stmt_uid, count, count, |
907 CGRAPH_FREQ_BASE, | |
908 true); | 903 true); |
909 for (e = indirect_calls; e; e=e->next_callee) | 904 for (e = indirect_calls; e; e=e->next_callee) |
910 if (!bbs_to_copy | 905 if (!bbs_to_copy |
911 || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index)) | 906 || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index)) |
912 e->clone (new_version, e->call_stmt, | 907 e->clone (new_version, e->call_stmt, |
913 e->lto_stmt_uid, count, count, | 908 e->lto_stmt_uid, count, count, |
914 CGRAPH_FREQ_BASE, | |
915 true); | 909 true); |
916 FOR_EACH_VEC_ELT (redirect_callers, i, e) | 910 FOR_EACH_VEC_ELT (redirect_callers, i, e) |
917 { | 911 { |
918 /* Redirect calls to the old version node to point to its new | 912 /* Redirect calls to the old version node to point to its new |
919 version. */ | 913 version. */ |
971 | 965 |
972 /* Generate a new name for the new version. */ | 966 /* Generate a new name for the new version. */ |
973 DECL_NAME (new_decl) = clone_function_name (old_decl, suffix); | 967 DECL_NAME (new_decl) = clone_function_name (old_decl, suffix); |
974 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl)); | 968 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl)); |
975 SET_DECL_RTL (new_decl, NULL); | 969 SET_DECL_RTL (new_decl, NULL); |
970 | |
971 DECL_VIRTUAL_P (new_decl) = 0; | |
976 | 972 |
977 /* When the old decl was a con-/destructor make sure the clone isn't. */ | 973 /* When the old decl was a con-/destructor make sure the clone isn't. */ |
978 DECL_STATIC_CONSTRUCTOR (new_decl) = 0; | 974 DECL_STATIC_CONSTRUCTOR (new_decl) = 0; |
979 DECL_STATIC_DESTRUCTOR (new_decl) = 0; | 975 DECL_STATIC_DESTRUCTOR (new_decl) = 0; |
980 | 976 |
1011 new_version_node->unique_name = true; | 1007 new_version_node->unique_name = true; |
1012 | 1008 |
1013 /* Update the call_expr on the edges to call the new version node. */ | 1009 /* Update the call_expr on the edges to call the new version node. */ |
1014 update_call_expr (new_version_node); | 1010 update_call_expr (new_version_node); |
1015 | 1011 |
1016 symtab->call_cgraph_insertion_hooks (this); | 1012 symtab->call_cgraph_insertion_hooks (new_version_node); |
1017 return new_version_node; | 1013 return new_version_node; |
1018 } | 1014 } |
1019 | 1015 |
1020 /* Given virtual clone, turn it into actual clone. */ | 1016 /* Given virtual clone, turn it into actual clone. */ |
1021 | 1017 |