]>
Commit | Line | Data |
---|---|---|
c02159a7 | 1 | /* Callgraph clones |
d353bf18 | 2 | Copyright (C) 2003-2015 Free Software Foundation, Inc. |
c02159a7 | 3 | Contributed by Jan Hubicka |
4 | ||
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify it under | |
8 | the terms of the GNU General Public License as published by the Free | |
9 | Software Foundation; either version 3, or (at your option) any later | |
10 | version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 | for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GCC; see the file COPYING3. If not see | |
19 | <http://www.gnu.org/licenses/>. */ | |
20 | ||
21 | /* This module provide facilities for clonning functions. I.e. creating | |
22 | new functions based on existing functions with simple modifications, | |
23 | such as replacement of parameters. | |
24 | ||
25 | To allow whole program optimization without actual presence of function | |
26 | bodies, an additional infrastructure is provided for so-called virtual | |
27 | clones | |
28 | ||
29 | A virtual clone in the callgraph is a function that has no | |
30 | associated body, just a description of how to create its body based | |
31 | on a different function (which itself may be a virtual clone). | |
32 | ||
33 | The description of function modifications includes adjustments to | |
34 | the function's signature (which allows, for example, removing or | |
35 | adding function arguments), substitutions to perform on the | |
36 | function body, and, for inlined functions, a pointer to the | |
37 | function that it will be inlined into. | |
38 | ||
39 | It is also possible to redirect any edge of the callgraph from a | |
40 | function to its virtual clone. This implies updating of the call | |
41 | site to adjust for the new function signature. | |
42 | ||
43 | Most of the transformations performed by inter-procedural | |
44 | optimizations can be represented via virtual clones. For | |
45 | instance, a constant propagation pass can produce a virtual clone | |
46 | of the function which replaces one of its arguments by a | |
47 | constant. The inliner can represent its decisions by producing a | |
48 | clone of a function whose body will be later integrated into | |
49 | a given function. | |
50 | ||
51 | Using virtual clones, the program can be easily updated | |
52 | during the Execute stage, solving most of pass interactions | |
53 | problems that would otherwise occur during Transform. | |
54 | ||
55 | Virtual clones are later materialized in the LTRANS stage and | |
56 | turned into real functions. Passes executed after the virtual | |
57 | clone were introduced also perform their Transform stage | |
58 | on new functions, so for a pass there is no significant | |
59 | difference between operating on a real function or a virtual | |
60 | clone introduced before its Execute stage. | |
61 | ||
62 | Optimization passes then work on virtual clones introduced before | |
63 | their Execute stage as if they were real functions. The | |
64 | only difference is that clones are not visible during the | |
65 | Generate Summary stage. */ | |
66 | ||
67 | #include "config.h" | |
68 | #include "system.h" | |
69 | #include "coretypes.h" | |
70 | #include "tm.h" | |
9ed99284 | 71 | #include "rtl.h" |
a3020f2f | 72 | #include "hash-set.h" |
b20a8bb4 | 73 | #include "vec.h" |
b20a8bb4 | 74 | #include "input.h" |
75 | #include "alias.h" | |
76 | #include "symtab.h" | |
b20a8bb4 | 77 | #include "inchash.h" |
78 | #include "tree.h" | |
79 | #include "fold-const.h" | |
80 | #include "stringpool.h" | |
a3020f2f | 81 | #include "hard-reg-set.h" |
82 | #include "input.h" | |
9ed99284 | 83 | #include "function.h" |
84 | #include "emit-rtl.h" | |
94ea8568 | 85 | #include "predict.h" |
bc61cadb | 86 | #include "basic-block.h" |
87 | #include "tree-ssa-alias.h" | |
88 | #include "internal-fn.h" | |
89 | #include "tree-eh.h" | |
90 | #include "gimple-expr.h" | |
91 | #include "is-a.h" | |
b23fb4cb | 92 | #include "gimple.h" |
073c1fd5 | 93 | #include "bitmap.h" |
94 | #include "tree-cfg.h" | |
c02159a7 | 95 | #include "tree-inline.h" |
96 | #include "langhooks.h" | |
c02159a7 | 97 | #include "toplev.h" |
98 | #include "flags.h" | |
c02159a7 | 99 | #include "debug.h" |
100 | #include "target.h" | |
c02159a7 | 101 | #include "diagnostic.h" |
c02159a7 | 102 | #include "params.h" |
c02159a7 | 103 | #include "intl.h" |
1140c305 | 104 | #include "hash-map.h" |
105 | #include "plugin-api.h" | |
106 | #include "ipa-ref.h" | |
107 | #include "cgraph.h" | |
108 | #include "alloc-pool.h" | |
2cc80ac3 | 109 | #include "symbol-summary.h" |
c02159a7 | 110 | #include "ipa-prop.h" |
c02159a7 | 111 | #include "tree-iterator.h" |
c02159a7 | 112 | #include "tree-dump.h" |
113 | #include "gimple-pretty-print.h" | |
c02159a7 | 114 | #include "coverage.h" |
c02159a7 | 115 | #include "ipa-inline.h" |
116 | #include "ipa-utils.h" | |
117 | #include "lto-streamer.h" | |
118 | #include "except.h" | |
119 | ||
35ee1c66 | 120 | /* Create clone of edge in the node N represented by CALL_EXPR |
121 | the callgraph. */ | |
122 | ||
123 | cgraph_edge * | |
1a91d914 | 124 | cgraph_edge::clone (cgraph_node *n, gcall *call_stmt, unsigned stmt_uid, |
35ee1c66 | 125 | gcov_type count_scale, int freq_scale, bool update_original) |
c02159a7 | 126 | { |
35ee1c66 | 127 | cgraph_edge *new_edge; |
128 | gcov_type gcov_count = apply_probability (count, count_scale); | |
c02159a7 | 129 | gcov_type freq; |
130 | ||
131 | /* We do not want to ignore loop nest after frequency drops to 0. */ | |
132 | if (!freq_scale) | |
133 | freq_scale = 1; | |
35ee1c66 | 134 | freq = frequency * (gcov_type) freq_scale / CGRAPH_FREQ_BASE; |
c02159a7 | 135 | if (freq > CGRAPH_FREQ_MAX) |
136 | freq = CGRAPH_FREQ_MAX; | |
137 | ||
35ee1c66 | 138 | if (indirect_unknown_callee) |
c02159a7 | 139 | { |
140 | tree decl; | |
141 | ||
9ccaed86 | 142 | if (call_stmt && (decl = gimple_call_fndecl (call_stmt)) |
143 | /* When the call is speculative, we need to resolve it | |
144 | via cgraph_resolve_speculation and not here. */ | |
35ee1c66 | 145 | && !speculative) |
c02159a7 | 146 | { |
35ee1c66 | 147 | cgraph_node *callee = cgraph_node::get (decl); |
c02159a7 | 148 | gcc_checking_assert (callee); |
35ee1c66 | 149 | new_edge = n->create_edge (callee, call_stmt, gcov_count, freq); |
c02159a7 | 150 | } |
151 | else | |
152 | { | |
415d1b9a | 153 | new_edge = n->create_indirect_edge (call_stmt, |
35ee1c66 | 154 | indirect_info->ecf_flags, |
39c98dee | 155 | count, freq, false); |
35ee1c66 | 156 | *new_edge->indirect_info = *indirect_info; |
c02159a7 | 157 | } |
158 | } | |
159 | else | |
160 | { | |
35ee1c66 | 161 | new_edge = n->create_edge (callee, call_stmt, gcov_count, freq); |
162 | if (indirect_info) | |
c02159a7 | 163 | { |
164 | new_edge->indirect_info | |
25a27413 | 165 | = ggc_cleared_alloc<cgraph_indirect_call_info> (); |
35ee1c66 | 166 | *new_edge->indirect_info = *indirect_info; |
c02159a7 | 167 | } |
168 | } | |
169 | ||
35ee1c66 | 170 | new_edge->inline_failed = inline_failed; |
171 | new_edge->indirect_inlining_edge = indirect_inlining_edge; | |
c02159a7 | 172 | new_edge->lto_stmt_uid = stmt_uid; |
173 | /* Clone flags that depend on call_stmt availability manually. */ | |
35ee1c66 | 174 | new_edge->can_throw_external = can_throw_external; |
175 | new_edge->call_stmt_cannot_inline_p = call_stmt_cannot_inline_p; | |
176 | new_edge->speculative = speculative; | |
007a6c27 | 177 | new_edge->in_polymorphic_cdtor = in_polymorphic_cdtor; |
c02159a7 | 178 | if (update_original) |
179 | { | |
35ee1c66 | 180 | count -= new_edge->count; |
181 | if (count < 0) | |
182 | count = 0; | |
c02159a7 | 183 | } |
35ee1c66 | 184 | symtab->call_edge_duplication_hooks (this, new_edge); |
c02159a7 | 185 | return new_edge; |
186 | } | |
187 | ||
98d52bcd | 188 | /* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP and the |
189 | return value if SKIP_RETURN is true. */ | |
190 | ||
191 | static tree | |
192 | build_function_type_skip_args (tree orig_type, bitmap args_to_skip, | |
193 | bool skip_return) | |
194 | { | |
195 | tree new_type = NULL; | |
40e1cddf | 196 | tree args, new_args = NULL; |
98d52bcd | 197 | tree new_reversed; |
198 | int i = 0; | |
199 | ||
200 | for (args = TYPE_ARG_TYPES (orig_type); args && args != void_list_node; | |
201 | args = TREE_CHAIN (args), i++) | |
202 | if (!args_to_skip || !bitmap_bit_p (args_to_skip, i)) | |
203 | new_args = tree_cons (NULL_TREE, TREE_VALUE (args), new_args); | |
204 | ||
205 | new_reversed = nreverse (new_args); | |
206 | if (args) | |
207 | { | |
208 | if (new_reversed) | |
209 | TREE_CHAIN (new_args) = void_list_node; | |
210 | else | |
211 | new_reversed = void_list_node; | |
212 | } | |
213 | ||
214 | /* Use copy_node to preserve as much as possible from original type | |
215 | (debug info, attribute lists etc.) | |
216 | Exception is METHOD_TYPEs must have THIS argument. | |
217 | When we are asked to remove it, we need to build new FUNCTION_TYPE | |
218 | instead. */ | |
219 | if (TREE_CODE (orig_type) != METHOD_TYPE | |
220 | || !args_to_skip | |
221 | || !bitmap_bit_p (args_to_skip, 0)) | |
222 | { | |
223 | new_type = build_distinct_type_copy (orig_type); | |
224 | TYPE_ARG_TYPES (new_type) = new_reversed; | |
225 | } | |
226 | else | |
227 | { | |
228 | new_type | |
229 | = build_distinct_type_copy (build_function_type (TREE_TYPE (orig_type), | |
230 | new_reversed)); | |
231 | TYPE_CONTEXT (new_type) = TYPE_CONTEXT (orig_type); | |
232 | } | |
233 | ||
234 | if (skip_return) | |
235 | TREE_TYPE (new_type) = void_type_node; | |
236 | ||
98d52bcd | 237 | return new_type; |
238 | } | |
239 | ||
240 | /* Build variant of function decl ORIG_DECL skipping ARGS_TO_SKIP and the | |
241 | return value if SKIP_RETURN is true. | |
242 | ||
243 | Arguments from DECL_ARGUMENTS list can't be removed now, since they are | |
244 | linked by TREE_CHAIN directly. The caller is responsible for eliminating | |
245 | them when they are being duplicated (i.e. copy_arguments_for_versioning). */ | |
246 | ||
247 | static tree | |
248 | build_function_decl_skip_args (tree orig_decl, bitmap args_to_skip, | |
249 | bool skip_return) | |
250 | { | |
251 | tree new_decl = copy_node (orig_decl); | |
252 | tree new_type; | |
253 | ||
254 | new_type = TREE_TYPE (orig_decl); | |
255 | if (prototype_p (new_type) | |
256 | || (skip_return && !VOID_TYPE_P (TREE_TYPE (new_type)))) | |
257 | new_type | |
258 | = build_function_type_skip_args (new_type, args_to_skip, skip_return); | |
259 | TREE_TYPE (new_decl) = new_type; | |
260 | ||
261 | /* For declarations setting DECL_VINDEX (i.e. methods) | |
262 | we expect first argument to be THIS pointer. */ | |
263 | if (args_to_skip && bitmap_bit_p (args_to_skip, 0)) | |
264 | DECL_VINDEX (new_decl) = NULL_TREE; | |
265 | ||
266 | /* When signature changes, we need to clear builtin info. */ | |
267 | if (DECL_BUILT_IN (new_decl) | |
268 | && args_to_skip | |
269 | && !bitmap_empty_p (args_to_skip)) | |
270 | { | |
271 | DECL_BUILT_IN_CLASS (new_decl) = NOT_BUILT_IN; | |
272 | DECL_FUNCTION_CODE (new_decl) = (enum built_in_function) 0; | |
273 | } | |
274 | /* The FE might have information and assumptions about the other | |
275 | arguments. */ | |
276 | DECL_LANG_SPECIFIC (new_decl) = NULL; | |
277 | return new_decl; | |
278 | } | |
279 | ||
280 | /* Set flags of NEW_NODE and its decl. NEW_NODE is a newly created private | |
281 | clone or its thunk. */ | |
282 | ||
283 | static void | |
284 | set_new_clone_decl_and_node_flags (cgraph_node *new_node) | |
285 | { | |
286 | DECL_EXTERNAL (new_node->decl) = 0; | |
98d52bcd | 287 | TREE_PUBLIC (new_node->decl) = 0; |
288 | DECL_COMDAT (new_node->decl) = 0; | |
289 | DECL_WEAK (new_node->decl) = 0; | |
290 | DECL_VIRTUAL_P (new_node->decl) = 0; | |
291 | DECL_STATIC_CONSTRUCTOR (new_node->decl) = 0; | |
292 | DECL_STATIC_DESTRUCTOR (new_node->decl) = 0; | |
293 | ||
294 | new_node->externally_visible = 0; | |
295 | new_node->local.local = 1; | |
296 | new_node->lowered = true; | |
297 | } | |
298 | ||
299 | /* Duplicate thunk THUNK if necessary but make it to refer to NODE. | |
300 | ARGS_TO_SKIP, if non-NULL, determines which parameters should be omitted. | |
301 | Function can return NODE if no thunk is necessary, which can happen when | |
302 | thunk is this_adjusting but we are removing this parameter. */ | |
303 | ||
304 | static cgraph_node * | |
2e1475da | 305 | duplicate_thunk_for_node (cgraph_node *thunk, cgraph_node *node) |
98d52bcd | 306 | { |
307 | cgraph_node *new_thunk, *thunk_of; | |
415d1b9a | 308 | thunk_of = thunk->callees->callee->ultimate_alias_target (); |
98d52bcd | 309 | |
310 | if (thunk_of->thunk.thunk_p) | |
2e1475da | 311 | node = duplicate_thunk_for_node (thunk_of, node); |
98d52bcd | 312 | |
a3a6d499 | 313 | if (!DECL_ARGUMENTS (thunk->decl)) |
4560777c | 314 | thunk->get_untransformed_body (); |
a3a6d499 | 315 | |
35ee1c66 | 316 | cgraph_edge *cs; |
98d52bcd | 317 | for (cs = node->callers; cs; cs = cs->next_caller) |
318 | if (cs->caller->thunk.thunk_p | |
319 | && cs->caller->thunk.this_adjusting == thunk->thunk.this_adjusting | |
320 | && cs->caller->thunk.fixed_offset == thunk->thunk.fixed_offset | |
321 | && cs->caller->thunk.virtual_offset_p == thunk->thunk.virtual_offset_p | |
322 | && cs->caller->thunk.virtual_value == thunk->thunk.virtual_value) | |
323 | return cs->caller; | |
324 | ||
325 | tree new_decl; | |
2e1475da | 326 | if (!node->clone.args_to_skip) |
98d52bcd | 327 | new_decl = copy_node (thunk->decl); |
328 | else | |
329 | { | |
330 | /* We do not need to duplicate this_adjusting thunks if we have removed | |
331 | this. */ | |
332 | if (thunk->thunk.this_adjusting | |
2e1475da | 333 | && bitmap_bit_p (node->clone.args_to_skip, 0)) |
98d52bcd | 334 | return node; |
335 | ||
2e1475da | 336 | new_decl = build_function_decl_skip_args (thunk->decl, |
337 | node->clone.args_to_skip, | |
98d52bcd | 338 | false); |
339 | } | |
d779c7b1 | 340 | |
341 | tree *link = &DECL_ARGUMENTS (new_decl); | |
342 | int i = 0; | |
343 | for (tree pd = DECL_ARGUMENTS (thunk->decl); pd; pd = DECL_CHAIN (pd), i++) | |
344 | { | |
345 | if (!node->clone.args_to_skip | |
346 | || !bitmap_bit_p (node->clone.args_to_skip, i)) | |
347 | { | |
348 | tree nd = copy_node (pd); | |
349 | DECL_CONTEXT (nd) = new_decl; | |
350 | *link = nd; | |
351 | link = &DECL_CHAIN (nd); | |
352 | } | |
353 | } | |
354 | *link = NULL_TREE; | |
355 | ||
98d52bcd | 356 | gcc_checking_assert (!DECL_STRUCT_FUNCTION (new_decl)); |
357 | gcc_checking_assert (!DECL_INITIAL (new_decl)); | |
358 | gcc_checking_assert (!DECL_RESULT (new_decl)); | |
359 | gcc_checking_assert (!DECL_RTL_SET_P (new_decl)); | |
360 | ||
361 | DECL_NAME (new_decl) = clone_function_name (thunk->decl, "artificial_thunk"); | |
362 | SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl)); | |
98d52bcd | 363 | |
415d1b9a | 364 | new_thunk = cgraph_node::create (new_decl); |
98d52bcd | 365 | set_new_clone_decl_and_node_flags (new_thunk); |
366 | new_thunk->definition = true; | |
367 | new_thunk->thunk = thunk->thunk; | |
368 | new_thunk->unique_name = in_lto_p; | |
369 | new_thunk->former_clone_of = thunk->decl; | |
2e1475da | 370 | new_thunk->clone.args_to_skip = node->clone.args_to_skip; |
371 | new_thunk->clone.combined_args_to_skip = node->clone.combined_args_to_skip; | |
98d52bcd | 372 | |
35ee1c66 | 373 | cgraph_edge *e = new_thunk->create_edge (node, NULL, 0, |
415d1b9a | 374 | CGRAPH_FREQ_BASE); |
98d52bcd | 375 | e->call_stmt_cannot_inline_p = true; |
35ee1c66 | 376 | symtab->call_edge_duplication_hooks (thunk->callees, e); |
35ee1c66 | 377 | symtab->call_cgraph_duplication_hooks (thunk, new_thunk); |
98d52bcd | 378 | return new_thunk; |
379 | } | |
380 | ||
381 | /* If E does not lead to a thunk, simply redirect it to N. Otherwise create | |
382 | one or more equivalent thunks for N and redirect E to the first in the | |
fe3c9f1e | 383 | chain. Note that it is then necessary to call |
384 | n->expand_all_artificial_thunks once all callers are redirected. */ | |
98d52bcd | 385 | |
386 | void | |
fe3c9f1e | 387 | cgraph_edge::redirect_callee_duplicating_thunks (cgraph_node *n) |
98d52bcd | 388 | { |
fe3c9f1e | 389 | cgraph_node *orig_to = callee->ultimate_alias_target (); |
98d52bcd | 390 | if (orig_to->thunk.thunk_p) |
2e1475da | 391 | n = duplicate_thunk_for_node (orig_to, n); |
98d52bcd | 392 | |
fe3c9f1e | 393 | redirect_callee (n); |
394 | } | |
395 | ||
396 | /* Call expand_thunk on all callers that are thunks and if analyze those nodes | |
397 | that were expanded. */ | |
398 | ||
399 | void | |
400 | cgraph_node::expand_all_artificial_thunks () | |
401 | { | |
402 | cgraph_edge *e; | |
403 | for (e = callers; e;) | |
404 | if (e->caller->thunk.thunk_p) | |
405 | { | |
406 | cgraph_node *thunk = e->caller; | |
407 | ||
408 | e = e->next_caller; | |
409 | if (thunk->expand_thunk (false, false)) | |
410 | { | |
411 | thunk->thunk.thunk_p = false; | |
412 | thunk->analyze (); | |
413 | } | |
414 | thunk->expand_all_artificial_thunks (); | |
415 | } | |
416 | else | |
417 | e = e->next_caller; | |
98d52bcd | 418 | } |
c02159a7 | 419 | |
420 | /* Create node representing clone of N executed COUNT times. Decrease | |
421 | the execution counts from original node too. | |
422 | The new clone will have decl set to DECL that may or may not be the same | |
423 | as decl of N. | |
424 | ||
425 | When UPDATE_ORIGINAL is true, the counts are subtracted from the original | |
426 | function's profile to reflect the fact that part of execution is handled | |
427 | by node. | |
428 | When CALL_DUPLICATOIN_HOOK is true, the ipa passes are acknowledged about | |
48f42a9a | 429 | the new clone. Otherwise the caller is responsible for doing so later. |
430 | ||
431 | If the new node is being inlined into another one, NEW_INLINED_TO should be | |
432 | the outline function the new one is (even indirectly) inlined to. All hooks | |
433 | will see this in node's global.inlined_to, when invoked. Can be NULL if the | |
434 | node is not inlined. */ | |
c02159a7 | 435 | |
415d1b9a | 436 | cgraph_node * |
c28f0245 | 437 | cgraph_node::create_clone (tree new_decl, gcov_type gcov_count, int freq, |
415d1b9a | 438 | bool update_original, |
439 | vec<cgraph_edge *> redirect_callers, | |
440 | bool call_duplication_hook, | |
35ee1c66 | 441 | cgraph_node *new_inlined_to, |
415d1b9a | 442 | bitmap args_to_skip) |
c02159a7 | 443 | { |
35ee1c66 | 444 | cgraph_node *new_node = symtab->create_empty (); |
445 | cgraph_edge *e; | |
c02159a7 | 446 | gcov_type count_scale; |
447 | unsigned i; | |
448 | ||
c28f0245 | 449 | new_node->decl = new_decl; |
415d1b9a | 450 | new_node->register_symbol (); |
451 | new_node->origin = origin; | |
452 | new_node->lto_file_data = lto_file_data; | |
c02159a7 | 453 | if (new_node->origin) |
454 | { | |
455 | new_node->next_nested = new_node->origin->nested; | |
456 | new_node->origin->nested = new_node; | |
457 | } | |
415d1b9a | 458 | new_node->analyzed = analyzed; |
459 | new_node->definition = definition; | |
460 | new_node->local = local; | |
02774f2d | 461 | new_node->externally_visible = false; |
6b722052 | 462 | new_node->no_reorder = no_reorder; |
c02159a7 | 463 | new_node->local.local = true; |
415d1b9a | 464 | new_node->global = global; |
48f42a9a | 465 | new_node->global.inlined_to = new_inlined_to; |
415d1b9a | 466 | new_node->rtl = rtl; |
c02159a7 | 467 | new_node->count = count; |
415d1b9a | 468 | new_node->frequency = frequency; |
469 | new_node->tp_first_run = tp_first_run; | |
f852c239 | 470 | new_node->tm_clone = tm_clone; |
ce7711df | 471 | new_node->icf_merged = icf_merged; |
472 | new_node->merged = merged; | |
2e1475da | 473 | |
474 | new_node->clone.tree_map = NULL; | |
475 | new_node->clone.args_to_skip = args_to_skip; | |
c28f0245 | 476 | new_node->split_part = split_part; |
2e1475da | 477 | if (!args_to_skip) |
415d1b9a | 478 | new_node->clone.combined_args_to_skip = clone.combined_args_to_skip; |
479 | else if (clone.combined_args_to_skip) | |
2e1475da | 480 | { |
481 | new_node->clone.combined_args_to_skip = BITMAP_GGC_ALLOC (); | |
482 | bitmap_ior (new_node->clone.combined_args_to_skip, | |
415d1b9a | 483 | clone.combined_args_to_skip, args_to_skip); |
2e1475da | 484 | } |
485 | else | |
486 | new_node->clone.combined_args_to_skip = args_to_skip; | |
487 | ||
415d1b9a | 488 | if (count) |
c02159a7 | 489 | { |
415d1b9a | 490 | if (new_node->count > count) |
c02159a7 | 491 | count_scale = REG_BR_PROB_BASE; |
492 | else | |
415d1b9a | 493 | count_scale = GCOV_COMPUTE_SCALE (new_node->count, count); |
c02159a7 | 494 | } |
495 | else | |
496 | count_scale = 0; | |
497 | if (update_original) | |
498 | { | |
415d1b9a | 499 | count -= gcov_count; |
500 | if (count < 0) | |
501 | count = 0; | |
c02159a7 | 502 | } |
503 | ||
f1f41a6c | 504 | FOR_EACH_VEC_ELT (redirect_callers, i, e) |
c02159a7 | 505 | { |
506 | /* Redirect calls to the old version node to point to its new | |
5a7ad253 | 507 | version. The only exception is when the edge was proved to |
508 | be unreachable during the clonning procedure. */ | |
509 | if (!e->callee | |
510 | || DECL_BUILT_IN_CLASS (e->callee->decl) != BUILT_IN_NORMAL | |
511 | || DECL_FUNCTION_CODE (e->callee->decl) != BUILT_IN_UNREACHABLE) | |
fe3c9f1e | 512 | e->redirect_callee_duplicating_thunks (new_node); |
c02159a7 | 513 | } |
fe3c9f1e | 514 | new_node->expand_all_artificial_thunks (); |
c02159a7 | 515 | |
415d1b9a | 516 | for (e = callees;e; e=e->next_callee) |
35ee1c66 | 517 | e->clone (new_node, e->call_stmt, e->lto_stmt_uid, count_scale, |
518 | freq, update_original); | |
c02159a7 | 519 | |
415d1b9a | 520 | for (e = indirect_calls; e; e = e->next_callee) |
35ee1c66 | 521 | e->clone (new_node, e->call_stmt, e->lto_stmt_uid, |
522 | count_scale, freq, update_original); | |
415d1b9a | 523 | new_node->clone_references (this); |
c02159a7 | 524 | |
415d1b9a | 525 | new_node->next_sibling_clone = clones; |
526 | if (clones) | |
527 | clones->prev_sibling_clone = new_node; | |
528 | clones = new_node; | |
529 | new_node->clone_of = this; | |
c02159a7 | 530 | |
531 | if (call_duplication_hook) | |
35ee1c66 | 532 | symtab->call_cgraph_duplication_hooks (this, new_node); |
c02159a7 | 533 | return new_node; |
534 | } | |
535 | ||
c02159a7 | 536 | static GTY(()) unsigned int clone_fn_id_num; |
537 | ||
a73afd90 | 538 | /* Return a new assembler name for a clone with SUFFIX of a decl named |
539 | NAME. */ | |
540 | ||
c02159a7 | 541 | tree |
a73afd90 | 542 | clone_function_name_1 (const char *name, const char *suffix) |
c02159a7 | 543 | { |
a73afd90 | 544 | size_t len = strlen (name); |
c02159a7 | 545 | char *tmp_name, *prefix; |
546 | ||
547 | prefix = XALLOCAVEC (char, len + strlen (suffix) + 2); | |
a73afd90 | 548 | memcpy (prefix, name, len); |
c02159a7 | 549 | strcpy (prefix + len + 1, suffix); |
550 | #ifndef NO_DOT_IN_LABEL | |
551 | prefix[len] = '.'; | |
552 | #elif !defined NO_DOLLAR_IN_LABEL | |
553 | prefix[len] = '$'; | |
554 | #else | |
555 | prefix[len] = '_'; | |
556 | #endif | |
557 | ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, clone_fn_id_num++); | |
558 | return get_identifier (tmp_name); | |
559 | } | |
560 | ||
a73afd90 | 561 | /* Return a new assembler name for a clone of DECL with SUFFIX. */ |
562 | ||
563 | tree | |
564 | clone_function_name (tree decl, const char *suffix) | |
565 | { | |
566 | tree name = DECL_ASSEMBLER_NAME (decl); | |
567 | return clone_function_name_1 (IDENTIFIER_POINTER (name), suffix); | |
568 | } | |
569 | ||
570 | ||
c02159a7 | 571 | /* Create callgraph node clone with new declaration. The actual body will |
572 | be copied later at compilation stage. | |
573 | ||
574 | TODO: after merging in ipa-sra use function call notes instead of args_to_skip | |
575 | bitmap interface. | |
576 | */ | |
35ee1c66 | 577 | cgraph_node * |
415d1b9a | 578 | cgraph_node::create_virtual_clone (vec<cgraph_edge *> redirect_callers, |
579 | vec<ipa_replace_map *, va_gc> *tree_map, | |
580 | bitmap args_to_skip, const char * suffix) | |
c02159a7 | 581 | { |
415d1b9a | 582 | tree old_decl = decl; |
35ee1c66 | 583 | cgraph_node *new_node = NULL; |
c02159a7 | 584 | tree new_decl; |
cac1ceba | 585 | size_t len, i; |
35ee1c66 | 586 | ipa_replace_map *map; |
cac1ceba | 587 | char *name; |
c02159a7 | 588 | |
eaad46f2 | 589 | if (!in_lto_p) |
022a2340 | 590 | gcc_checking_assert (tree_versionable_function_p (old_decl)); |
c02159a7 | 591 | |
415d1b9a | 592 | gcc_assert (local.can_change_signature || !args_to_skip); |
c02159a7 | 593 | |
594 | /* Make a new FUNCTION_DECL tree node */ | |
595 | if (!args_to_skip) | |
596 | new_decl = copy_node (old_decl); | |
597 | else | |
598 | new_decl = build_function_decl_skip_args (old_decl, args_to_skip, false); | |
79e830ee | 599 | |
600 | /* These pointers represent function body and will be populated only when clone | |
601 | is materialized. */ | |
602 | gcc_assert (new_decl != old_decl); | |
c02159a7 | 603 | DECL_STRUCT_FUNCTION (new_decl) = NULL; |
79e830ee | 604 | DECL_ARGUMENTS (new_decl) = NULL; |
605 | DECL_INITIAL (new_decl) = NULL; | |
606 | DECL_RESULT (new_decl) = NULL; | |
607 | /* We can not do DECL_RESULT (new_decl) = NULL; here because of LTO partitioning | |
608 | sometimes storing only clone decl instead of original. */ | |
c02159a7 | 609 | |
610 | /* Generate a new name for the new version. */ | |
cac1ceba | 611 | len = IDENTIFIER_LENGTH (DECL_NAME (old_decl)); |
612 | name = XALLOCAVEC (char, len + strlen (suffix) + 2); | |
613 | memcpy (name, IDENTIFIER_POINTER (DECL_NAME (old_decl)), len); | |
614 | strcpy (name + len + 1, suffix); | |
615 | name[len] = '.'; | |
616 | DECL_NAME (new_decl) = get_identifier (name); | |
617 | SET_DECL_ASSEMBLER_NAME (new_decl, clone_function_name (old_decl, suffix)); | |
c02159a7 | 618 | SET_DECL_RTL (new_decl, NULL); |
619 | ||
415d1b9a | 620 | new_node = create_clone (new_decl, count, CGRAPH_FREQ_BASE, false, |
621 | redirect_callers, false, NULL, args_to_skip); | |
622 | ||
c02159a7 | 623 | /* Update the properties. |
624 | Make clone visible only within this translation unit. Make sure | |
625 | that is not weak also. | |
626 | ??? We cannot use COMDAT linkage because there is no | |
627 | ABI support for this. */ | |
98d52bcd | 628 | set_new_clone_decl_and_node_flags (new_node); |
c02159a7 | 629 | new_node->clone.tree_map = tree_map; |
033ab5d3 | 630 | if (!implicit_section) |
022a2340 | 631 | new_node->set_section (get_section ()); |
5c368d8a | 632 | |
633 | /* Clones of global symbols or symbols with unique names are unique. */ | |
634 | if ((TREE_PUBLIC (old_decl) | |
635 | && !DECL_EXTERNAL (old_decl) | |
636 | && !DECL_WEAK (old_decl) | |
637 | && !DECL_COMDAT (old_decl)) | |
638 | || in_lto_p) | |
02774f2d | 639 | new_node->unique_name = true; |
f1f41a6c | 640 | FOR_EACH_VEC_SAFE_ELT (tree_map, i, map) |
35ee1c66 | 641 | new_node->maybe_create_reference (map->new_tree, IPA_REF_ADDR, NULL); |
2e1475da | 642 | |
415d1b9a | 643 | if (ipa_transforms_to_apply.exists ()) |
2cf4c3b3 | 644 | new_node->ipa_transforms_to_apply |
415d1b9a | 645 | = ipa_transforms_to_apply.copy (); |
c02159a7 | 646 | |
35ee1c66 | 647 | symtab->call_cgraph_duplication_hooks (this, new_node); |
c02159a7 | 648 | |
649 | return new_node; | |
650 | } | |
651 | ||
415d1b9a | 652 | /* callgraph node being removed from symbol table; see if its entry can be |
653 | replaced by other inline clone. */ | |
654 | cgraph_node * | |
655 | cgraph_node::find_replacement (void) | |
c02159a7 | 656 | { |
35ee1c66 | 657 | cgraph_node *next_inline_clone, *replacement; |
c02159a7 | 658 | |
415d1b9a | 659 | for (next_inline_clone = clones; |
c02159a7 | 660 | next_inline_clone |
415d1b9a | 661 | && next_inline_clone->decl != decl; |
c02159a7 | 662 | next_inline_clone = next_inline_clone->next_sibling_clone) |
663 | ; | |
664 | ||
665 | /* If there is inline clone of the node being removed, we need | |
666 | to put it into the position of removed node and reorganize all | |
667 | other clones to be based on it. */ | |
668 | if (next_inline_clone) | |
669 | { | |
35ee1c66 | 670 | cgraph_node *n; |
671 | cgraph_node *new_clones; | |
c02159a7 | 672 | |
673 | replacement = next_inline_clone; | |
674 | ||
675 | /* Unlink inline clone from the list of clones of removed node. */ | |
676 | if (next_inline_clone->next_sibling_clone) | |
677 | next_inline_clone->next_sibling_clone->prev_sibling_clone | |
678 | = next_inline_clone->prev_sibling_clone; | |
679 | if (next_inline_clone->prev_sibling_clone) | |
680 | { | |
415d1b9a | 681 | gcc_assert (clones != next_inline_clone); |
c02159a7 | 682 | next_inline_clone->prev_sibling_clone->next_sibling_clone |
683 | = next_inline_clone->next_sibling_clone; | |
684 | } | |
685 | else | |
686 | { | |
415d1b9a | 687 | gcc_assert (clones == next_inline_clone); |
688 | clones = next_inline_clone->next_sibling_clone; | |
c02159a7 | 689 | } |
690 | ||
415d1b9a | 691 | new_clones = clones; |
692 | clones = NULL; | |
c02159a7 | 693 | |
694 | /* Copy clone info. */ | |
415d1b9a | 695 | next_inline_clone->clone = clone; |
c02159a7 | 696 | |
697 | /* Now place it into clone tree at same level at NODE. */ | |
415d1b9a | 698 | next_inline_clone->clone_of = clone_of; |
c02159a7 | 699 | next_inline_clone->prev_sibling_clone = NULL; |
700 | next_inline_clone->next_sibling_clone = NULL; | |
415d1b9a | 701 | if (clone_of) |
c02159a7 | 702 | { |
415d1b9a | 703 | if (clone_of->clones) |
704 | clone_of->clones->prev_sibling_clone = next_inline_clone; | |
705 | next_inline_clone->next_sibling_clone = clone_of->clones; | |
706 | clone_of->clones = next_inline_clone; | |
c02159a7 | 707 | } |
708 | ||
709 | /* Merge the clone list. */ | |
710 | if (new_clones) | |
711 | { | |
712 | if (!next_inline_clone->clones) | |
713 | next_inline_clone->clones = new_clones; | |
714 | else | |
715 | { | |
716 | n = next_inline_clone->clones; | |
717 | while (n->next_sibling_clone) | |
415d1b9a | 718 | n = n->next_sibling_clone; |
c02159a7 | 719 | n->next_sibling_clone = new_clones; |
720 | new_clones->prev_sibling_clone = n; | |
721 | } | |
722 | } | |
723 | ||
724 | /* Update clone_of pointers. */ | |
725 | n = new_clones; | |
726 | while (n) | |
727 | { | |
728 | n->clone_of = next_inline_clone; | |
729 | n = n->next_sibling_clone; | |
730 | } | |
731 | return replacement; | |
732 | } | |
733 | else | |
734 | return NULL; | |
735 | } | |
736 | ||
737 | /* Like cgraph_set_call_stmt but walk the clone tree and update all | |
4d044066 | 738 | clones sharing the same function body. |
739 | When WHOLE_SPECULATIVE_EDGES is true, all three components of | |
740 | speculative edge gets updated. Otherwise we update only direct | |
741 | call. */ | |
c02159a7 | 742 | |
743 | void | |
1a91d914 | 744 | cgraph_node::set_call_stmt_including_clones (gimple old_stmt, |
745 | gcall *new_stmt, | |
415d1b9a | 746 | bool update_speculative) |
c02159a7 | 747 | { |
35ee1c66 | 748 | cgraph_node *node; |
749 | cgraph_edge *edge = get_edge (old_stmt); | |
c02159a7 | 750 | |
751 | if (edge) | |
35ee1c66 | 752 | edge->set_call_stmt (new_stmt, update_speculative); |
c02159a7 | 753 | |
415d1b9a | 754 | node = clones; |
c02159a7 | 755 | if (node) |
415d1b9a | 756 | while (node != this) |
c02159a7 | 757 | { |
35ee1c66 | 758 | cgraph_edge *edge = node->get_edge (old_stmt); |
c02159a7 | 759 | if (edge) |
4d044066 | 760 | { |
35ee1c66 | 761 | edge->set_call_stmt (new_stmt, update_speculative); |
4d044066 | 762 | /* If UPDATE_SPECULATIVE is false, it means that we are turning |
763 | speculative call into a real code sequence. Update the | |
764 | callgraph edges. */ | |
765 | if (edge->speculative && !update_speculative) | |
766 | { | |
35ee1c66 | 767 | cgraph_edge *direct, *indirect; |
768 | ipa_ref *ref; | |
4d044066 | 769 | |
770 | gcc_assert (!edge->indirect_unknown_callee); | |
35ee1c66 | 771 | edge->speculative_call_info (direct, indirect, ref); |
4d044066 | 772 | direct->speculative = false; |
773 | indirect->speculative = false; | |
774 | ref->speculative = false; | |
775 | } | |
776 | } | |
c02159a7 | 777 | if (node->clones) |
778 | node = node->clones; | |
779 | else if (node->next_sibling_clone) | |
780 | node = node->next_sibling_clone; | |
781 | else | |
782 | { | |
415d1b9a | 783 | while (node != this && !node->next_sibling_clone) |
c02159a7 | 784 | node = node->clone_of; |
415d1b9a | 785 | if (node != this) |
c02159a7 | 786 | node = node->next_sibling_clone; |
787 | } | |
788 | } | |
789 | } | |
790 | ||
791 | /* Like cgraph_create_edge walk the clone tree and update all clones sharing | |
792 | same function body. If clones already have edge for OLD_STMT; only | |
793 | update the edge same way as cgraph_set_call_stmt_including_clones does. | |
794 | ||
795 | TODO: COUNT and LOOP_DEPTH should be properly distributed based on relative | |
796 | frequencies of the clones. */ | |
797 | ||
798 | void | |
35ee1c66 | 799 | cgraph_node::create_edge_including_clones (cgraph_node *callee, |
1a91d914 | 800 | gimple old_stmt, gcall *stmt, |
415d1b9a | 801 | gcov_type count, |
802 | int freq, | |
803 | cgraph_inline_failed_t reason) | |
c02159a7 | 804 | { |
35ee1c66 | 805 | cgraph_node *node; |
806 | cgraph_edge *edge; | |
c02159a7 | 807 | |
415d1b9a | 808 | if (!get_edge (stmt)) |
c02159a7 | 809 | { |
415d1b9a | 810 | edge = create_edge (callee, stmt, count, freq); |
c02159a7 | 811 | edge->inline_failed = reason; |
812 | } | |
813 | ||
415d1b9a | 814 | node = clones; |
c02159a7 | 815 | if (node) |
415d1b9a | 816 | while (node != this) |
c02159a7 | 817 | { |
35ee1c66 | 818 | cgraph_edge *edge = node->get_edge (old_stmt); |
c02159a7 | 819 | |
820 | /* It is possible that clones already contain the edge while | |
821 | master didn't. Either we promoted indirect call into direct | |
822 | call in the clone or we are processing clones of unreachable | |
823 | master where edges has been removed. */ | |
824 | if (edge) | |
35ee1c66 | 825 | edge->set_call_stmt (stmt); |
415d1b9a | 826 | else if (! node->get_edge (stmt)) |
c02159a7 | 827 | { |
415d1b9a | 828 | edge = node->create_edge (callee, stmt, count, freq); |
c02159a7 | 829 | edge->inline_failed = reason; |
830 | } | |
831 | ||
832 | if (node->clones) | |
833 | node = node->clones; | |
834 | else if (node->next_sibling_clone) | |
835 | node = node->next_sibling_clone; | |
836 | else | |
837 | { | |
415d1b9a | 838 | while (node != this && !node->next_sibling_clone) |
c02159a7 | 839 | node = node->clone_of; |
415d1b9a | 840 | if (node != this) |
c02159a7 | 841 | node = node->next_sibling_clone; |
842 | } | |
843 | } | |
844 | } | |
845 | ||
846 | /* Remove the node from cgraph and all inline clones inlined into it. | |
847 | Skip however removal of FORBIDDEN_NODE and return true if it needs to be | |
848 | removed. This allows to call the function from outer loop walking clone | |
849 | tree. */ | |
850 | ||
851 | bool | |
415d1b9a | 852 | cgraph_node::remove_symbol_and_inline_clones (cgraph_node *forbidden_node) |
c02159a7 | 853 | { |
35ee1c66 | 854 | cgraph_edge *e, *next; |
c02159a7 | 855 | bool found = false; |
856 | ||
415d1b9a | 857 | if (this == forbidden_node) |
8afc926b | 858 | { |
35ee1c66 | 859 | callers->remove (); |
8afc926b | 860 | return true; |
861 | } | |
415d1b9a | 862 | for (e = callees; e; e = next) |
c02159a7 | 863 | { |
864 | next = e->next_callee; | |
865 | if (!e->inline_failed) | |
415d1b9a | 866 | found |= e->callee->remove_symbol_and_inline_clones (forbidden_node); |
c02159a7 | 867 | } |
415d1b9a | 868 | remove (); |
c02159a7 | 869 | return found; |
870 | } | |
871 | ||
872 | /* The edges representing the callers of the NEW_VERSION node were | |
873 | fixed by cgraph_function_versioning (), now the call_expr in their | |
874 | respective tree code should be updated to call the NEW_VERSION. */ | |
875 | ||
876 | static void | |
35ee1c66 | 877 | update_call_expr (cgraph_node *new_version) |
c02159a7 | 878 | { |
35ee1c66 | 879 | cgraph_edge *e; |
c02159a7 | 880 | |
881 | gcc_assert (new_version); | |
882 | ||
883 | /* Update the call expr on the edges to call the new version. */ | |
884 | for (e = new_version->callers; e; e = e->next_caller) | |
885 | { | |
35ee1c66 | 886 | function *inner_function = DECL_STRUCT_FUNCTION (e->caller->decl); |
02774f2d | 887 | gimple_call_set_fndecl (e->call_stmt, new_version->decl); |
c02159a7 | 888 | maybe_clean_eh_stmt_fn (inner_function, e->call_stmt); |
889 | } | |
890 | } | |
891 | ||
892 | ||
893 | /* Create a new cgraph node which is the new version of | |
415d1b9a | 894 | callgraph node. REDIRECT_CALLERS holds the callers |
c02159a7 | 895 | edges which should be redirected to point to |
415d1b9a | 896 | NEW_VERSION. ALL the callees edges of the node |
c02159a7 | 897 | are cloned to the new version node. Return the new |
898 | version node. | |
899 | ||
900 | If non-NULL BLOCK_TO_COPY determine what basic blocks | |
901 | was copied to prevent duplications of calls that are dead | |
902 | in the clone. */ | |
903 | ||
415d1b9a | 904 | cgraph_node * |
905 | cgraph_node::create_version_clone (tree new_decl, | |
906 | vec<cgraph_edge *> redirect_callers, | |
907 | bitmap bbs_to_copy) | |
c02159a7 | 908 | { |
35ee1c66 | 909 | cgraph_node *new_version; |
910 | cgraph_edge *e; | |
c02159a7 | 911 | unsigned i; |
912 | ||
415d1b9a | 913 | new_version = cgraph_node::create (new_decl); |
c02159a7 | 914 | |
415d1b9a | 915 | new_version->analyzed = analyzed; |
916 | new_version->definition = definition; | |
917 | new_version->local = local; | |
02774f2d | 918 | new_version->externally_visible = false; |
6b722052 | 919 | new_version->no_reorder = no_reorder; |
02774f2d | 920 | new_version->local.local = new_version->definition; |
415d1b9a | 921 | new_version->global = global; |
922 | new_version->rtl = rtl; | |
923 | new_version->count = count; | |
c02159a7 | 924 | |
415d1b9a | 925 | for (e = callees; e; e=e->next_callee) |
c02159a7 | 926 | if (!bbs_to_copy |
927 | || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index)) | |
35ee1c66 | 928 | e->clone (new_version, e->call_stmt, |
929 | e->lto_stmt_uid, REG_BR_PROB_BASE, | |
930 | CGRAPH_FREQ_BASE, | |
931 | true); | |
415d1b9a | 932 | for (e = indirect_calls; e; e=e->next_callee) |
c02159a7 | 933 | if (!bbs_to_copy |
934 | || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index)) | |
35ee1c66 | 935 | e->clone (new_version, e->call_stmt, |
936 | e->lto_stmt_uid, REG_BR_PROB_BASE, | |
937 | CGRAPH_FREQ_BASE, | |
938 | true); | |
f1f41a6c | 939 | FOR_EACH_VEC_ELT (redirect_callers, i, e) |
c02159a7 | 940 | { |
941 | /* Redirect calls to the old version node to point to its new | |
942 | version. */ | |
35ee1c66 | 943 | e->redirect_callee (new_version); |
c02159a7 | 944 | } |
945 | ||
35ee1c66 | 946 | symtab->call_cgraph_duplication_hooks (this, new_version); |
c02159a7 | 947 | |
948 | return new_version; | |
949 | } | |
950 | ||
951 | /* Perform function versioning. | |
952 | Function versioning includes copying of the tree and | |
953 | a callgraph update (creating a new cgraph node and updating | |
954 | its callees and callers). | |
955 | ||
956 | REDIRECT_CALLERS varray includes the edges to be redirected | |
957 | to the new version. | |
958 | ||
959 | TREE_MAP is a mapping of tree nodes we want to replace with | |
960 | new ones (according to results of prior analysis). | |
c02159a7 | 961 | |
962 | If non-NULL ARGS_TO_SKIP determine function parameters to remove | |
963 | from new version. | |
964 | If SKIP_RETURN is true, the new version will return void. | |
965 | If non-NULL BLOCK_TO_COPY determine what basic blocks to copy. | |
966 | If non_NULL NEW_ENTRY determine new entry BB of the clone. | |
967 | ||
968 | Return the new version's cgraph node. */ | |
969 | ||
415d1b9a | 970 | cgraph_node * |
971 | cgraph_node::create_version_clone_with_body | |
972 | (vec<cgraph_edge *> redirect_callers, | |
973 | vec<ipa_replace_map *, va_gc> *tree_map, bitmap args_to_skip, | |
974 | bool skip_return, bitmap bbs_to_copy, basic_block new_entry_block, | |
975 | const char *clone_name) | |
c02159a7 | 976 | { |
415d1b9a | 977 | tree old_decl = decl; |
35ee1c66 | 978 | cgraph_node *new_version_node = NULL; |
c02159a7 | 979 | tree new_decl; |
980 | ||
981 | if (!tree_versionable_function_p (old_decl)) | |
982 | return NULL; | |
983 | ||
415d1b9a | 984 | gcc_assert (local.can_change_signature || !args_to_skip); |
c02159a7 | 985 | |
986 | /* Make a new FUNCTION_DECL tree node for the new version. */ | |
987 | if (!args_to_skip && !skip_return) | |
988 | new_decl = copy_node (old_decl); | |
989 | else | |
990 | new_decl | |
991 | = build_function_decl_skip_args (old_decl, args_to_skip, skip_return); | |
992 | ||
993 | /* Generate a new name for the new version. */ | |
994 | DECL_NAME (new_decl) = clone_function_name (old_decl, clone_name); | |
995 | SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl)); | |
996 | SET_DECL_RTL (new_decl, NULL); | |
997 | ||
998 | /* When the old decl was a con-/destructor make sure the clone isn't. */ | |
9af5ce0c | 999 | DECL_STATIC_CONSTRUCTOR (new_decl) = 0; |
1000 | DECL_STATIC_DESTRUCTOR (new_decl) = 0; | |
c02159a7 | 1001 | |
1002 | /* Create the new version's call-graph node. | |
1003 | and update the edges of the new node. */ | |
415d1b9a | 1004 | new_version_node = create_version_clone (new_decl, redirect_callers, |
1005 | bbs_to_copy); | |
c02159a7 | 1006 | |
415d1b9a | 1007 | if (ipa_transforms_to_apply.exists ()) |
9be0994b | 1008 | new_version_node->ipa_transforms_to_apply |
415d1b9a | 1009 | = ipa_transforms_to_apply.copy (); |
c02159a7 | 1010 | /* Copy the OLD_VERSION_NODE function tree to the new version. */ |
1011 | tree_function_versioning (old_decl, new_decl, tree_map, false, args_to_skip, | |
1012 | skip_return, bbs_to_copy, new_entry_block); | |
1013 | ||
1014 | /* Update the new version's properties. | |
1015 | Make The new version visible only within this translation unit. Make sure | |
1016 | that is not weak also. | |
1017 | ??? We cannot use COMDAT linkage because there is no | |
1018 | ABI support for this. */ | |
415d1b9a | 1019 | new_version_node->make_decl_local (); |
02774f2d | 1020 | DECL_VIRTUAL_P (new_version_node->decl) = 0; |
1021 | new_version_node->externally_visible = 0; | |
c02159a7 | 1022 | new_version_node->local.local = 1; |
1023 | new_version_node->lowered = true; | |
033ab5d3 | 1024 | if (!implicit_section) |
1025 | new_version_node->set_section (get_section ()); | |
5c368d8a | 1026 | /* Clones of global symbols or symbols with unique names are unique. */ |
1027 | if ((TREE_PUBLIC (old_decl) | |
1028 | && !DECL_EXTERNAL (old_decl) | |
1029 | && !DECL_WEAK (old_decl) | |
1030 | && !DECL_COMDAT (old_decl)) | |
1031 | || in_lto_p) | |
02774f2d | 1032 | new_version_node->unique_name = true; |
c02159a7 | 1033 | |
1034 | /* Update the call_expr on the edges to call the new version node. */ | |
1035 | update_call_expr (new_version_node); | |
1036 | ||
35ee1c66 | 1037 | symtab->call_cgraph_insertion_hooks (this); |
c02159a7 | 1038 | return new_version_node; |
1039 | } | |
1040 | ||
1041 | /* Given virtual clone, turn it into actual clone. */ | |
1042 | ||
1043 | static void | |
35ee1c66 | 1044 | cgraph_materialize_clone (cgraph_node *node) |
c02159a7 | 1045 | { |
1046 | bitmap_obstack_initialize (NULL); | |
02774f2d | 1047 | node->former_clone_of = node->clone_of->decl; |
c02159a7 | 1048 | if (node->clone_of->former_clone_of) |
1049 | node->former_clone_of = node->clone_of->former_clone_of; | |
1050 | /* Copy the OLD_VERSION_NODE function tree to the new version. */ | |
02774f2d | 1051 | tree_function_versioning (node->clone_of->decl, node->decl, |
c02159a7 | 1052 | node->clone.tree_map, true, |
1053 | node->clone.args_to_skip, false, | |
1054 | NULL, NULL); | |
35ee1c66 | 1055 | if (symtab->dump_file) |
c02159a7 | 1056 | { |
35ee1c66 | 1057 | dump_function_to_file (node->clone_of->decl, symtab->dump_file, |
1058 | dump_flags); | |
1059 | dump_function_to_file (node->decl, symtab->dump_file, dump_flags); | |
c02159a7 | 1060 | } |
1061 | ||
1062 | /* Function is no longer clone. */ | |
1063 | if (node->next_sibling_clone) | |
1064 | node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone; | |
1065 | if (node->prev_sibling_clone) | |
1066 | node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone; | |
1067 | else | |
1068 | node->clone_of->clones = node->next_sibling_clone; | |
1069 | node->next_sibling_clone = NULL; | |
1070 | node->prev_sibling_clone = NULL; | |
02774f2d | 1071 | if (!node->clone_of->analyzed && !node->clone_of->clones) |
c02159a7 | 1072 | { |
415d1b9a | 1073 | node->clone_of->release_body (); |
1074 | node->clone_of->remove_callees (); | |
51ce5652 | 1075 | node->clone_of->remove_all_references (); |
c02159a7 | 1076 | } |
1077 | node->clone_of = NULL; | |
1078 | bitmap_obstack_release (NULL); | |
1079 | } | |
1080 | ||
1081 | /* Once all functions from compilation unit are in memory, produce all clones | |
1082 | and update all calls. We might also do this on demand if we don't want to | |
1083 | bring all functions to memory prior compilation, but current WHOPR | |
1084 | implementation does that and it is is bit easier to keep everything right in | |
1085 | this order. */ | |
1086 | ||
1087 | void | |
35ee1c66 | 1088 | symbol_table::materialize_all_clones (void) |
c02159a7 | 1089 | { |
35ee1c66 | 1090 | cgraph_node *node; |
c02159a7 | 1091 | bool stabilized = false; |
4d044066 | 1092 | |
c02159a7 | 1093 | |
35ee1c66 | 1094 | if (symtab->dump_file) |
1095 | fprintf (symtab->dump_file, "Materializing clones\n"); | |
c02159a7 | 1096 | #ifdef ENABLE_CHECKING |
415d1b9a | 1097 | cgraph_node::verify_cgraph_nodes (); |
c02159a7 | 1098 | #endif |
1099 | ||
1100 | /* We can also do topological order, but number of iterations should be | |
1101 | bounded by number of IPA passes since single IPA pass is probably not | |
1102 | going to create clones of clones it created itself. */ | |
1103 | while (!stabilized) | |
1104 | { | |
1105 | stabilized = true; | |
1106 | FOR_EACH_FUNCTION (node) | |
1107 | { | |
02774f2d | 1108 | if (node->clone_of && node->decl != node->clone_of->decl |
1109 | && !gimple_has_body_p (node->decl)) | |
c02159a7 | 1110 | { |
eaad46f2 | 1111 | if (!node->clone_of->clone_of) |
4560777c | 1112 | node->clone_of->get_untransformed_body (); |
02774f2d | 1113 | if (gimple_has_body_p (node->clone_of->decl)) |
c02159a7 | 1114 | { |
35ee1c66 | 1115 | if (symtab->dump_file) |
c02159a7 | 1116 | { |
35ee1c66 | 1117 | fprintf (symtab->dump_file, "cloning %s to %s\n", |
5ae49d3e | 1118 | xstrdup_for_dump (node->clone_of->name ()), |
1119 | xstrdup_for_dump (node->name ())); | |
c02159a7 | 1120 | if (node->clone.tree_map) |
1121 | { | |
1122 | unsigned int i; | |
35ee1c66 | 1123 | fprintf (symtab->dump_file, " replace map: "); |
f1f41a6c | 1124 | for (i = 0; |
1125 | i < vec_safe_length (node->clone.tree_map); | |
1126 | i++) | |
c02159a7 | 1127 | { |
35ee1c66 | 1128 | ipa_replace_map *replace_info; |
f1f41a6c | 1129 | replace_info = (*node->clone.tree_map)[i]; |
35ee1c66 | 1130 | print_generic_expr (symtab->dump_file, replace_info->old_tree, 0); |
1131 | fprintf (symtab->dump_file, " -> "); | |
1132 | print_generic_expr (symtab->dump_file, replace_info->new_tree, 0); | |
1133 | fprintf (symtab->dump_file, "%s%s;", | |
c02159a7 | 1134 | replace_info->replace_p ? "(replace)":"", |
1135 | replace_info->ref_p ? "(ref)":""); | |
1136 | } | |
35ee1c66 | 1137 | fprintf (symtab->dump_file, "\n"); |
c02159a7 | 1138 | } |
1139 | if (node->clone.args_to_skip) | |
1140 | { | |
35ee1c66 | 1141 | fprintf (symtab->dump_file, " args_to_skip: "); |
1142 | dump_bitmap (symtab->dump_file, | |
1143 | node->clone.args_to_skip); | |
c02159a7 | 1144 | } |
1145 | if (node->clone.args_to_skip) | |
1146 | { | |
35ee1c66 | 1147 | fprintf (symtab->dump_file, " combined_args_to_skip:"); |
1148 | dump_bitmap (symtab->dump_file, node->clone.combined_args_to_skip); | |
c02159a7 | 1149 | } |
1150 | } | |
1151 | cgraph_materialize_clone (node); | |
1152 | stabilized = false; | |
1153 | } | |
1154 | } | |
1155 | } | |
1156 | } | |
1157 | FOR_EACH_FUNCTION (node) | |
02774f2d | 1158 | if (!node->analyzed && node->callees) |
9df17e79 | 1159 | { |
415d1b9a | 1160 | node->remove_callees (); |
51ce5652 | 1161 | node->remove_all_references (); |
9df17e79 | 1162 | } |
1163 | else | |
51ce5652 | 1164 | node->clear_stmts_in_references (); |
35ee1c66 | 1165 | if (symtab->dump_file) |
1166 | fprintf (symtab->dump_file, "Materialization Call site updates done.\n"); | |
c02159a7 | 1167 | #ifdef ENABLE_CHECKING |
415d1b9a | 1168 | cgraph_node::verify_cgraph_nodes (); |
c02159a7 | 1169 | #endif |
366970c6 | 1170 | symtab->remove_unreachable_nodes (symtab->dump_file); |
c02159a7 | 1171 | } |
1172 | ||
1173 | #include "gt-cgraphclones.h" |