]> gcc.gnu.org Git - gcc.git/blame - gcc/cgraphclones.c
arm.md (arm_addsi3, [...]): Correct output template.
[gcc.git] / gcc / cgraphclones.c
CommitLineData
564fe867 1/* Callgraph clones
d1e082c2 2 Copyright (C) 2003-2013 Free Software Foundation, Inc.
564fe867
JH
3 Contributed by Jan Hubicka
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along 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"
71#include "tree.h"
564fe867
JH
72#include "rtl.h"
73#include "tree-flow.h"
74#include "tree-inline.h"
75#include "langhooks.h"
76#include "pointer-set.h"
77#include "toplev.h"
78#include "flags.h"
79#include "ggc.h"
80#include "debug.h"
81#include "target.h"
82#include "cgraph.h"
83#include "diagnostic.h"
564fe867 84#include "params.h"
564fe867
JH
85#include "intl.h"
86#include "function.h"
87#include "ipa-prop.h"
88#include "gimple.h"
89#include "tree-iterator.h"
564fe867
JH
90#include "tree-dump.h"
91#include "gimple-pretty-print.h"
564fe867 92#include "coverage.h"
564fe867
JH
93#include "ipa-inline.h"
94#include "ipa-utils.h"
95#include "lto-streamer.h"
96#include "except.h"
97
98/* Create clone of E in the node N represented by CALL_EXPR the callgraph. */
99struct cgraph_edge *
100cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n,
101 gimple call_stmt, unsigned stmt_uid, gcov_type count_scale,
102 int freq_scale, bool update_original)
103{
104 struct cgraph_edge *new_edge;
8b47039c 105 gcov_type count = apply_probability (e->count, count_scale);
564fe867
JH
106 gcov_type freq;
107
108 /* We do not want to ignore loop nest after frequency drops to 0. */
109 if (!freq_scale)
110 freq_scale = 1;
111 freq = e->frequency * (gcov_type) freq_scale / CGRAPH_FREQ_BASE;
112 if (freq > CGRAPH_FREQ_MAX)
113 freq = CGRAPH_FREQ_MAX;
114
115 if (e->indirect_unknown_callee)
116 {
117 tree decl;
118
119 if (call_stmt && (decl = gimple_call_fndecl (call_stmt)))
120 {
121 struct cgraph_node *callee = cgraph_get_node (decl);
122 gcc_checking_assert (callee);
123 new_edge = cgraph_create_edge (n, callee, call_stmt, count, freq);
124 }
125 else
126 {
127 new_edge = cgraph_create_indirect_edge (n, call_stmt,
128 e->indirect_info->ecf_flags,
129 count, freq);
130 *new_edge->indirect_info = *e->indirect_info;
131 }
132 }
133 else
134 {
135 new_edge = cgraph_create_edge (n, e->callee, call_stmt, count, freq);
136 if (e->indirect_info)
137 {
138 new_edge->indirect_info
139 = ggc_alloc_cleared_cgraph_indirect_call_info ();
140 *new_edge->indirect_info = *e->indirect_info;
141 }
142 }
143
144 new_edge->inline_failed = e->inline_failed;
145 new_edge->indirect_inlining_edge = e->indirect_inlining_edge;
146 new_edge->lto_stmt_uid = stmt_uid;
147 /* Clone flags that depend on call_stmt availability manually. */
148 new_edge->can_throw_external = e->can_throw_external;
149 new_edge->call_stmt_cannot_inline_p = e->call_stmt_cannot_inline_p;
150 if (update_original)
151 {
152 e->count -= new_edge->count;
153 if (e->count < 0)
154 e->count = 0;
155 }
156 cgraph_call_edge_duplication_hooks (e, new_edge);
157 return new_edge;
158}
159
160
161/* Create node representing clone of N executed COUNT times. Decrease
162 the execution counts from original node too.
163 The new clone will have decl set to DECL that may or may not be the same
164 as decl of N.
165
166 When UPDATE_ORIGINAL is true, the counts are subtracted from the original
167 function's profile to reflect the fact that part of execution is handled
168 by node.
169 When CALL_DUPLICATOIN_HOOK is true, the ipa passes are acknowledged about
44a60244
MJ
170 the new clone. Otherwise the caller is responsible for doing so later.
171
172 If the new node is being inlined into another one, NEW_INLINED_TO should be
173 the outline function the new one is (even indirectly) inlined to. All hooks
174 will see this in node's global.inlined_to, when invoked. Can be NULL if the
175 node is not inlined. */
564fe867
JH
176
177struct cgraph_node *
178cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq,
179 bool update_original,
9771b263 180 vec<cgraph_edge_p> redirect_callers,
44a60244
MJ
181 bool call_duplication_hook,
182 struct cgraph_node *new_inlined_to)
564fe867
JH
183{
184 struct cgraph_node *new_node = cgraph_create_empty_node ();
185 struct cgraph_edge *e;
186 gcov_type count_scale;
187 unsigned i;
188
189 new_node->symbol.decl = decl;
190 symtab_register_node ((symtab_node)new_node);
191 new_node->origin = n->origin;
a19b1432 192 new_node->symbol.lto_file_data = n->symbol.lto_file_data;
564fe867
JH
193 if (new_node->origin)
194 {
195 new_node->next_nested = new_node->origin->nested;
196 new_node->origin->nested = new_node;
197 }
e70670cf
JH
198 new_node->symbol.analyzed = n->symbol.analyzed;
199 new_node->symbol.definition = n->symbol.definition;
564fe867
JH
200 new_node->local = n->local;
201 new_node->symbol.externally_visible = false;
202 new_node->local.local = true;
203 new_node->global = n->global;
44a60244 204 new_node->global.inlined_to = new_inlined_to;
564fe867
JH
205 new_node->rtl = n->rtl;
206 new_node->count = count;
207 new_node->frequency = n->frequency;
208 new_node->clone = n->clone;
9771b263 209 new_node->clone.tree_map = NULL;
564fe867
JH
210 if (n->count)
211 {
212 if (new_node->count > n->count)
213 count_scale = REG_BR_PROB_BASE;
214 else
8b47039c 215 count_scale = GCOV_COMPUTE_SCALE (new_node->count, n->count);
564fe867
JH
216 }
217 else
218 count_scale = 0;
219 if (update_original)
220 {
221 n->count -= count;
222 if (n->count < 0)
223 n->count = 0;
224 }
225
9771b263 226 FOR_EACH_VEC_ELT (redirect_callers, i, e)
564fe867
JH
227 {
228 /* Redirect calls to the old version node to point to its new
229 version. */
230 cgraph_redirect_edge_callee (e, new_node);
231 }
232
233
234 for (e = n->callees;e; e=e->next_callee)
235 cgraph_clone_edge (e, new_node, e->call_stmt, e->lto_stmt_uid,
236 count_scale, freq, update_original);
237
238 for (e = n->indirect_calls; e; e = e->next_callee)
239 cgraph_clone_edge (e, new_node, e->call_stmt, e->lto_stmt_uid,
240 count_scale, freq, update_original);
241 ipa_clone_references ((symtab_node)new_node, &n->symbol.ref_list);
242
243 new_node->next_sibling_clone = n->clones;
244 if (n->clones)
245 n->clones->prev_sibling_clone = new_node;
246 n->clones = new_node;
247 new_node->clone_of = n;
248
249 if (call_duplication_hook)
250 cgraph_call_node_duplication_hooks (n, new_node);
251 return new_node;
252}
253
254/* Create a new name for clone of DECL, add SUFFIX. Returns an identifier. */
255
256static GTY(()) unsigned int clone_fn_id_num;
257
258tree
259clone_function_name (tree decl, const char *suffix)
260{
261 tree name = DECL_ASSEMBLER_NAME (decl);
262 size_t len = IDENTIFIER_LENGTH (name);
263 char *tmp_name, *prefix;
264
265 prefix = XALLOCAVEC (char, len + strlen (suffix) + 2);
266 memcpy (prefix, IDENTIFIER_POINTER (name), len);
267 strcpy (prefix + len + 1, suffix);
268#ifndef NO_DOT_IN_LABEL
269 prefix[len] = '.';
270#elif !defined NO_DOLLAR_IN_LABEL
271 prefix[len] = '$';
272#else
273 prefix[len] = '_';
274#endif
275 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, clone_fn_id_num++);
276 return get_identifier (tmp_name);
277}
278
279/* Create callgraph node clone with new declaration. The actual body will
280 be copied later at compilation stage.
281
282 TODO: after merging in ipa-sra use function call notes instead of args_to_skip
283 bitmap interface.
284 */
285struct cgraph_node *
286cgraph_create_virtual_clone (struct cgraph_node *old_node,
9771b263
DN
287 vec<cgraph_edge_p> redirect_callers,
288 vec<ipa_replace_map_p, va_gc> *tree_map,
564fe867
JH
289 bitmap args_to_skip,
290 const char * suffix)
291{
292 tree old_decl = old_node->symbol.decl;
293 struct cgraph_node *new_node = NULL;
294 tree new_decl;
295 size_t i;
296 struct ipa_replace_map *map;
297
298 if (!flag_wpa)
299 gcc_checking_assert (tree_versionable_function_p (old_decl));
300
301 gcc_assert (old_node->local.can_change_signature || !args_to_skip);
302
303 /* Make a new FUNCTION_DECL tree node */
304 if (!args_to_skip)
305 new_decl = copy_node (old_decl);
306 else
307 new_decl = build_function_decl_skip_args (old_decl, args_to_skip, false);
308 DECL_STRUCT_FUNCTION (new_decl) = NULL;
309
310 /* Generate a new name for the new version. */
311 DECL_NAME (new_decl) = clone_function_name (old_decl, suffix);
312 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
313 SET_DECL_RTL (new_decl, NULL);
314
315 new_node = cgraph_clone_node (old_node, new_decl, old_node->count,
316 CGRAPH_FREQ_BASE, false,
44a60244 317 redirect_callers, false, NULL);
564fe867
JH
318 /* Update the properties.
319 Make clone visible only within this translation unit. Make sure
320 that is not weak also.
321 ??? We cannot use COMDAT linkage because there is no
322 ABI support for this. */
323 DECL_EXTERNAL (new_node->symbol.decl) = 0;
324 if (DECL_ONE_ONLY (old_decl))
325 DECL_SECTION_NAME (new_node->symbol.decl) = NULL;
326 DECL_COMDAT_GROUP (new_node->symbol.decl) = 0;
327 TREE_PUBLIC (new_node->symbol.decl) = 0;
328 DECL_COMDAT (new_node->symbol.decl) = 0;
329 DECL_WEAK (new_node->symbol.decl) = 0;
8222c37e 330 DECL_VIRTUAL_P (new_node->symbol.decl) = 0;
564fe867
JH
331 DECL_STATIC_CONSTRUCTOR (new_node->symbol.decl) = 0;
332 DECL_STATIC_DESTRUCTOR (new_node->symbol.decl) = 0;
333 new_node->clone.tree_map = tree_map;
334 new_node->clone.args_to_skip = args_to_skip;
702d8703
JH
335
336 /* Clones of global symbols or symbols with unique names are unique. */
337 if ((TREE_PUBLIC (old_decl)
338 && !DECL_EXTERNAL (old_decl)
339 && !DECL_WEAK (old_decl)
340 && !DECL_COMDAT (old_decl))
341 || in_lto_p)
342 new_node->symbol.unique_name = true;
9771b263 343 FOR_EACH_VEC_SAFE_ELT (tree_map, i, map)
79ee9826
MJ
344 ipa_maybe_record_reference ((symtab_node) new_node, map->new_tree,
345 IPA_REF_ADDR, NULL);
564fe867
JH
346 if (!args_to_skip)
347 new_node->clone.combined_args_to_skip = old_node->clone.combined_args_to_skip;
348 else if (old_node->clone.combined_args_to_skip)
349 {
350 int newi = 0, oldi = 0;
351 tree arg;
352 bitmap new_args_to_skip = BITMAP_GGC_ALLOC ();
353 struct cgraph_node *orig_node;
354 for (orig_node = old_node; orig_node->clone_of; orig_node = orig_node->clone_of)
355 ;
356 for (arg = DECL_ARGUMENTS (orig_node->symbol.decl);
357 arg; arg = DECL_CHAIN (arg), oldi++)
358 {
359 if (bitmap_bit_p (old_node->clone.combined_args_to_skip, oldi))
360 {
361 bitmap_set_bit (new_args_to_skip, oldi);
362 continue;
363 }
364 if (bitmap_bit_p (args_to_skip, newi))
365 bitmap_set_bit (new_args_to_skip, oldi);
366 newi++;
367 }
368 new_node->clone.combined_args_to_skip = new_args_to_skip;
369 }
370 else
371 new_node->clone.combined_args_to_skip = args_to_skip;
372 new_node->symbol.externally_visible = 0;
373 new_node->local.local = 1;
374 new_node->lowered = true;
375
376 cgraph_call_node_duplication_hooks (old_node, new_node);
377
378
379 return new_node;
380}
381
382/* NODE is being removed from symbol table; see if its entry can be replaced by
383 other inline clone. */
384struct cgraph_node *
385cgraph_find_replacement_node (struct cgraph_node *node)
386{
387 struct cgraph_node *next_inline_clone, *replacement;
388
389 for (next_inline_clone = node->clones;
390 next_inline_clone
391 && next_inline_clone->symbol.decl != node->symbol.decl;
392 next_inline_clone = next_inline_clone->next_sibling_clone)
393 ;
394
395 /* If there is inline clone of the node being removed, we need
396 to put it into the position of removed node and reorganize all
397 other clones to be based on it. */
398 if (next_inline_clone)
399 {
400 struct cgraph_node *n;
401 struct cgraph_node *new_clones;
402
403 replacement = next_inline_clone;
404
405 /* Unlink inline clone from the list of clones of removed node. */
406 if (next_inline_clone->next_sibling_clone)
407 next_inline_clone->next_sibling_clone->prev_sibling_clone
408 = next_inline_clone->prev_sibling_clone;
409 if (next_inline_clone->prev_sibling_clone)
410 {
411 gcc_assert (node->clones != next_inline_clone);
412 next_inline_clone->prev_sibling_clone->next_sibling_clone
413 = next_inline_clone->next_sibling_clone;
414 }
415 else
416 {
417 gcc_assert (node->clones == next_inline_clone);
418 node->clones = next_inline_clone->next_sibling_clone;
419 }
420
421 new_clones = node->clones;
422 node->clones = NULL;
423
424 /* Copy clone info. */
425 next_inline_clone->clone = node->clone;
426
427 /* Now place it into clone tree at same level at NODE. */
428 next_inline_clone->clone_of = node->clone_of;
429 next_inline_clone->prev_sibling_clone = NULL;
430 next_inline_clone->next_sibling_clone = NULL;
431 if (node->clone_of)
432 {
433 if (node->clone_of->clones)
434 node->clone_of->clones->prev_sibling_clone = next_inline_clone;
435 next_inline_clone->next_sibling_clone = node->clone_of->clones;
436 node->clone_of->clones = next_inline_clone;
437 }
438
439 /* Merge the clone list. */
440 if (new_clones)
441 {
442 if (!next_inline_clone->clones)
443 next_inline_clone->clones = new_clones;
444 else
445 {
446 n = next_inline_clone->clones;
447 while (n->next_sibling_clone)
448 n = n->next_sibling_clone;
449 n->next_sibling_clone = new_clones;
450 new_clones->prev_sibling_clone = n;
451 }
452 }
453
454 /* Update clone_of pointers. */
455 n = new_clones;
456 while (n)
457 {
458 n->clone_of = next_inline_clone;
459 n = n->next_sibling_clone;
460 }
461 return replacement;
462 }
463 else
464 return NULL;
465}
466
467/* Like cgraph_set_call_stmt but walk the clone tree and update all
468 clones sharing the same function body. */
469
470void
471cgraph_set_call_stmt_including_clones (struct cgraph_node *orig,
472 gimple old_stmt, gimple new_stmt)
473{
474 struct cgraph_node *node;
475 struct cgraph_edge *edge = cgraph_edge (orig, old_stmt);
476
477 if (edge)
478 cgraph_set_call_stmt (edge, new_stmt);
479
480 node = orig->clones;
481 if (node)
482 while (node != orig)
483 {
484 struct cgraph_edge *edge = cgraph_edge (node, old_stmt);
485 if (edge)
486 cgraph_set_call_stmt (edge, new_stmt);
487 if (node->clones)
488 node = node->clones;
489 else if (node->next_sibling_clone)
490 node = node->next_sibling_clone;
491 else
492 {
493 while (node != orig && !node->next_sibling_clone)
494 node = node->clone_of;
495 if (node != orig)
496 node = node->next_sibling_clone;
497 }
498 }
499}
500
501/* Like cgraph_create_edge walk the clone tree and update all clones sharing
502 same function body. If clones already have edge for OLD_STMT; only
503 update the edge same way as cgraph_set_call_stmt_including_clones does.
504
505 TODO: COUNT and LOOP_DEPTH should be properly distributed based on relative
506 frequencies of the clones. */
507
508void
509cgraph_create_edge_including_clones (struct cgraph_node *orig,
510 struct cgraph_node *callee,
511 gimple old_stmt,
512 gimple stmt, gcov_type count,
513 int freq,
514 cgraph_inline_failed_t reason)
515{
516 struct cgraph_node *node;
517 struct cgraph_edge *edge;
518
519 if (!cgraph_edge (orig, stmt))
520 {
521 edge = cgraph_create_edge (orig, callee, stmt, count, freq);
522 edge->inline_failed = reason;
523 }
524
525 node = orig->clones;
526 if (node)
527 while (node != orig)
528 {
529 struct cgraph_edge *edge = cgraph_edge (node, old_stmt);
530
531 /* It is possible that clones already contain the edge while
532 master didn't. Either we promoted indirect call into direct
533 call in the clone or we are processing clones of unreachable
534 master where edges has been removed. */
535 if (edge)
536 cgraph_set_call_stmt (edge, stmt);
537 else if (!cgraph_edge (node, stmt))
538 {
539 edge = cgraph_create_edge (node, callee, stmt, count,
540 freq);
541 edge->inline_failed = reason;
542 }
543
544 if (node->clones)
545 node = node->clones;
546 else if (node->next_sibling_clone)
547 node = node->next_sibling_clone;
548 else
549 {
550 while (node != orig && !node->next_sibling_clone)
551 node = node->clone_of;
552 if (node != orig)
553 node = node->next_sibling_clone;
554 }
555 }
556}
557
558/* Remove the node from cgraph and all inline clones inlined into it.
559 Skip however removal of FORBIDDEN_NODE and return true if it needs to be
560 removed. This allows to call the function from outer loop walking clone
561 tree. */
562
563bool
564cgraph_remove_node_and_inline_clones (struct cgraph_node *node, struct cgraph_node *forbidden_node)
565{
566 struct cgraph_edge *e, *next;
567 bool found = false;
568
569 if (node == forbidden_node)
39f9719e
JH
570 {
571 cgraph_remove_edge (node->callers);
572 return true;
573 }
564fe867
JH
574 for (e = node->callees; e; e = next)
575 {
576 next = e->next_callee;
577 if (!e->inline_failed)
578 found |= cgraph_remove_node_and_inline_clones (e->callee, forbidden_node);
579 }
580 cgraph_remove_node (node);
581 return found;
582}
583
584/* The edges representing the callers of the NEW_VERSION node were
585 fixed by cgraph_function_versioning (), now the call_expr in their
586 respective tree code should be updated to call the NEW_VERSION. */
587
588static void
589update_call_expr (struct cgraph_node *new_version)
590{
591 struct cgraph_edge *e;
592
593 gcc_assert (new_version);
594
595 /* Update the call expr on the edges to call the new version. */
596 for (e = new_version->callers; e; e = e->next_caller)
597 {
598 struct function *inner_function = DECL_STRUCT_FUNCTION (e->caller->symbol.decl);
599 gimple_call_set_fndecl (e->call_stmt, new_version->symbol.decl);
600 maybe_clean_eh_stmt_fn (inner_function, e->call_stmt);
601 }
602}
603
604
605/* Create a new cgraph node which is the new version of
606 OLD_VERSION node. REDIRECT_CALLERS holds the callers
607 edges which should be redirected to point to
608 NEW_VERSION. ALL the callees edges of OLD_VERSION
609 are cloned to the new version node. Return the new
610 version node.
611
612 If non-NULL BLOCK_TO_COPY determine what basic blocks
613 was copied to prevent duplications of calls that are dead
614 in the clone. */
615
616struct cgraph_node *
617cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
618 tree new_decl,
9771b263 619 vec<cgraph_edge_p> redirect_callers,
564fe867
JH
620 bitmap bbs_to_copy)
621 {
622 struct cgraph_node *new_version;
623 struct cgraph_edge *e;
624 unsigned i;
625
626 gcc_assert (old_version);
627
628 new_version = cgraph_create_node (new_decl);
629
e70670cf
JH
630 new_version->symbol.analyzed = old_version->symbol.analyzed;
631 new_version->symbol.definition = old_version->symbol.definition;
564fe867
JH
632 new_version->local = old_version->local;
633 new_version->symbol.externally_visible = false;
e70670cf 634 new_version->local.local = new_version->symbol.definition;
564fe867
JH
635 new_version->global = old_version->global;
636 new_version->rtl = old_version->rtl;
637 new_version->count = old_version->count;
638
639 for (e = old_version->callees; e; e=e->next_callee)
640 if (!bbs_to_copy
641 || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index))
642 cgraph_clone_edge (e, new_version, e->call_stmt,
643 e->lto_stmt_uid, REG_BR_PROB_BASE,
644 CGRAPH_FREQ_BASE,
645 true);
646 for (e = old_version->indirect_calls; e; e=e->next_callee)
647 if (!bbs_to_copy
648 || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index))
649 cgraph_clone_edge (e, new_version, e->call_stmt,
650 e->lto_stmt_uid, REG_BR_PROB_BASE,
651 CGRAPH_FREQ_BASE,
652 true);
9771b263 653 FOR_EACH_VEC_ELT (redirect_callers, i, e)
564fe867
JH
654 {
655 /* Redirect calls to the old version node to point to its new
656 version. */
657 cgraph_redirect_edge_callee (e, new_version);
658 }
659
660 cgraph_call_node_duplication_hooks (old_version, new_version);
661
662 return new_version;
663 }
664
665/* Perform function versioning.
666 Function versioning includes copying of the tree and
667 a callgraph update (creating a new cgraph node and updating
668 its callees and callers).
669
670 REDIRECT_CALLERS varray includes the edges to be redirected
671 to the new version.
672
673 TREE_MAP is a mapping of tree nodes we want to replace with
674 new ones (according to results of prior analysis).
675 OLD_VERSION_NODE is the node that is versioned.
676
677 If non-NULL ARGS_TO_SKIP determine function parameters to remove
678 from new version.
679 If SKIP_RETURN is true, the new version will return void.
680 If non-NULL BLOCK_TO_COPY determine what basic blocks to copy.
681 If non_NULL NEW_ENTRY determine new entry BB of the clone.
682
683 Return the new version's cgraph node. */
684
685struct cgraph_node *
686cgraph_function_versioning (struct cgraph_node *old_version_node,
9771b263
DN
687 vec<cgraph_edge_p> redirect_callers,
688 vec<ipa_replace_map_p, va_gc> *tree_map,
564fe867
JH
689 bitmap args_to_skip,
690 bool skip_return,
691 bitmap bbs_to_copy,
692 basic_block new_entry_block,
693 const char *clone_name)
694{
695 tree old_decl = old_version_node->symbol.decl;
696 struct cgraph_node *new_version_node = NULL;
697 tree new_decl;
698
699 if (!tree_versionable_function_p (old_decl))
700 return NULL;
701
702 gcc_assert (old_version_node->local.can_change_signature || !args_to_skip);
703
704 /* Make a new FUNCTION_DECL tree node for the new version. */
705 if (!args_to_skip && !skip_return)
706 new_decl = copy_node (old_decl);
707 else
708 new_decl
709 = build_function_decl_skip_args (old_decl, args_to_skip, skip_return);
710
711 /* Generate a new name for the new version. */
712 DECL_NAME (new_decl) = clone_function_name (old_decl, clone_name);
713 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
714 SET_DECL_RTL (new_decl, NULL);
715
716 /* When the old decl was a con-/destructor make sure the clone isn't. */
717 DECL_STATIC_CONSTRUCTOR(new_decl) = 0;
718 DECL_STATIC_DESTRUCTOR(new_decl) = 0;
719
720 /* Create the new version's call-graph node.
721 and update the edges of the new node. */
722 new_version_node =
723 cgraph_copy_node_for_versioning (old_version_node, new_decl,
724 redirect_callers, bbs_to_copy);
725
726 /* Copy the OLD_VERSION_NODE function tree to the new version. */
727 tree_function_versioning (old_decl, new_decl, tree_map, false, args_to_skip,
728 skip_return, bbs_to_copy, new_entry_block);
729
730 /* Update the new version's properties.
731 Make The new version visible only within this translation unit. Make sure
732 that is not weak also.
733 ??? We cannot use COMDAT linkage because there is no
734 ABI support for this. */
735 symtab_make_decl_local (new_version_node->symbol.decl);
736 DECL_VIRTUAL_P (new_version_node->symbol.decl) = 0;
737 new_version_node->symbol.externally_visible = 0;
738 new_version_node->local.local = 1;
739 new_version_node->lowered = true;
702d8703
JH
740 /* Clones of global symbols or symbols with unique names are unique. */
741 if ((TREE_PUBLIC (old_decl)
742 && !DECL_EXTERNAL (old_decl)
743 && !DECL_WEAK (old_decl)
744 && !DECL_COMDAT (old_decl))
745 || in_lto_p)
746 new_version_node->symbol.unique_name = true;
564fe867
JH
747
748 /* Update the call_expr on the edges to call the new version node. */
749 update_call_expr (new_version_node);
750
751 cgraph_call_function_insertion_hooks (new_version_node);
752 return new_version_node;
753}
754
755/* Given virtual clone, turn it into actual clone. */
756
757static void
758cgraph_materialize_clone (struct cgraph_node *node)
759{
760 bitmap_obstack_initialize (NULL);
761 node->former_clone_of = node->clone_of->symbol.decl;
762 if (node->clone_of->former_clone_of)
763 node->former_clone_of = node->clone_of->former_clone_of;
764 /* Copy the OLD_VERSION_NODE function tree to the new version. */
765 tree_function_versioning (node->clone_of->symbol.decl, node->symbol.decl,
766 node->clone.tree_map, true,
767 node->clone.args_to_skip, false,
768 NULL, NULL);
769 if (cgraph_dump_file)
770 {
771 dump_function_to_file (node->clone_of->symbol.decl, cgraph_dump_file, dump_flags);
772 dump_function_to_file (node->symbol.decl, cgraph_dump_file, dump_flags);
773 }
774
775 /* Function is no longer clone. */
776 if (node->next_sibling_clone)
777 node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone;
778 if (node->prev_sibling_clone)
779 node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
780 else
781 node->clone_of->clones = node->next_sibling_clone;
782 node->next_sibling_clone = NULL;
783 node->prev_sibling_clone = NULL;
e70670cf 784 if (!node->clone_of->symbol.analyzed && !node->clone_of->clones)
564fe867
JH
785 {
786 cgraph_release_function_body (node->clone_of);
787 cgraph_node_remove_callees (node->clone_of);
788 ipa_remove_all_references (&node->clone_of->symbol.ref_list);
789 }
790 node->clone_of = NULL;
791 bitmap_obstack_release (NULL);
792}
793
794/* Once all functions from compilation unit are in memory, produce all clones
795 and update all calls. We might also do this on demand if we don't want to
796 bring all functions to memory prior compilation, but current WHOPR
797 implementation does that and it is is bit easier to keep everything right in
798 this order. */
799
800void
801cgraph_materialize_all_clones (void)
802{
803 struct cgraph_node *node;
804 bool stabilized = false;
805
806 if (cgraph_dump_file)
807 fprintf (cgraph_dump_file, "Materializing clones\n");
808#ifdef ENABLE_CHECKING
809 verify_cgraph ();
810#endif
811
812 /* We can also do topological order, but number of iterations should be
813 bounded by number of IPA passes since single IPA pass is probably not
814 going to create clones of clones it created itself. */
815 while (!stabilized)
816 {
817 stabilized = true;
818 FOR_EACH_FUNCTION (node)
819 {
820 if (node->clone_of && node->symbol.decl != node->clone_of->symbol.decl
821 && !gimple_has_body_p (node->symbol.decl))
822 {
823 if (gimple_has_body_p (node->clone_of->symbol.decl))
824 {
825 if (cgraph_dump_file)
826 {
827 fprintf (cgraph_dump_file, "cloning %s to %s\n",
828 xstrdup (cgraph_node_name (node->clone_of)),
829 xstrdup (cgraph_node_name (node)));
830 if (node->clone.tree_map)
831 {
832 unsigned int i;
833 fprintf (cgraph_dump_file, " replace map: ");
9771b263
DN
834 for (i = 0;
835 i < vec_safe_length (node->clone.tree_map);
836 i++)
564fe867
JH
837 {
838 struct ipa_replace_map *replace_info;
9771b263 839 replace_info = (*node->clone.tree_map)[i];
564fe867
JH
840 print_generic_expr (cgraph_dump_file, replace_info->old_tree, 0);
841 fprintf (cgraph_dump_file, " -> ");
842 print_generic_expr (cgraph_dump_file, replace_info->new_tree, 0);
843 fprintf (cgraph_dump_file, "%s%s;",
844 replace_info->replace_p ? "(replace)":"",
845 replace_info->ref_p ? "(ref)":"");
846 }
847 fprintf (cgraph_dump_file, "\n");
848 }
849 if (node->clone.args_to_skip)
850 {
851 fprintf (cgraph_dump_file, " args_to_skip: ");
852 dump_bitmap (cgraph_dump_file, node->clone.args_to_skip);
853 }
854 if (node->clone.args_to_skip)
855 {
856 fprintf (cgraph_dump_file, " combined_args_to_skip:");
857 dump_bitmap (cgraph_dump_file, node->clone.combined_args_to_skip);
858 }
859 }
860 cgraph_materialize_clone (node);
861 stabilized = false;
862 }
863 }
864 }
865 }
866 FOR_EACH_FUNCTION (node)
e70670cf 867 if (!node->symbol.analyzed && node->callees)
564fe867
JH
868 cgraph_node_remove_callees (node);
869 if (cgraph_dump_file)
870 fprintf (cgraph_dump_file, "Materialization Call site updates done.\n");
871#ifdef ENABLE_CHECKING
872 verify_cgraph ();
873#endif
04142cc3 874 symtab_remove_unreachable_nodes (false, cgraph_dump_file);
564fe867
JH
875}
876
877#include "gt-cgraphclones.h"
This page took 0.413119 seconds and 5 git commands to generate.