]> gcc.gnu.org Git - gcc.git/blame - gcc/cgraphclones.c
go-gcc.cc (Gcc_backend::immutable_struct_set_init): Use compute_reloc_for_constant.
[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);
49bde175
JH
308
309 /* These pointers represent function body and will be populated only when clone
310 is materialized. */
311 gcc_assert (new_decl != old_decl);
564fe867 312 DECL_STRUCT_FUNCTION (new_decl) = NULL;
49bde175
JH
313 DECL_ARGUMENTS (new_decl) = NULL;
314 DECL_INITIAL (new_decl) = NULL;
315 DECL_RESULT (new_decl) = NULL;
316 /* We can not do DECL_RESULT (new_decl) = NULL; here because of LTO partitioning
317 sometimes storing only clone decl instead of original. */
564fe867
JH
318
319 /* Generate a new name for the new version. */
320 DECL_NAME (new_decl) = clone_function_name (old_decl, suffix);
321 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
322 SET_DECL_RTL (new_decl, NULL);
323
324 new_node = cgraph_clone_node (old_node, new_decl, old_node->count,
325 CGRAPH_FREQ_BASE, false,
44a60244 326 redirect_callers, false, NULL);
564fe867
JH
327 /* Update the properties.
328 Make clone visible only within this translation unit. Make sure
329 that is not weak also.
330 ??? We cannot use COMDAT linkage because there is no
331 ABI support for this. */
332 DECL_EXTERNAL (new_node->symbol.decl) = 0;
333 if (DECL_ONE_ONLY (old_decl))
334 DECL_SECTION_NAME (new_node->symbol.decl) = NULL;
335 DECL_COMDAT_GROUP (new_node->symbol.decl) = 0;
336 TREE_PUBLIC (new_node->symbol.decl) = 0;
337 DECL_COMDAT (new_node->symbol.decl) = 0;
338 DECL_WEAK (new_node->symbol.decl) = 0;
8222c37e 339 DECL_VIRTUAL_P (new_node->symbol.decl) = 0;
564fe867
JH
340 DECL_STATIC_CONSTRUCTOR (new_node->symbol.decl) = 0;
341 DECL_STATIC_DESTRUCTOR (new_node->symbol.decl) = 0;
342 new_node->clone.tree_map = tree_map;
343 new_node->clone.args_to_skip = args_to_skip;
702d8703
JH
344
345 /* Clones of global symbols or symbols with unique names are unique. */
346 if ((TREE_PUBLIC (old_decl)
347 && !DECL_EXTERNAL (old_decl)
348 && !DECL_WEAK (old_decl)
349 && !DECL_COMDAT (old_decl))
350 || in_lto_p)
351 new_node->symbol.unique_name = true;
9771b263 352 FOR_EACH_VEC_SAFE_ELT (tree_map, i, map)
79ee9826
MJ
353 ipa_maybe_record_reference ((symtab_node) new_node, map->new_tree,
354 IPA_REF_ADDR, NULL);
564fe867
JH
355 if (!args_to_skip)
356 new_node->clone.combined_args_to_skip = old_node->clone.combined_args_to_skip;
357 else if (old_node->clone.combined_args_to_skip)
358 {
359 int newi = 0, oldi = 0;
360 tree arg;
361 bitmap new_args_to_skip = BITMAP_GGC_ALLOC ();
362 struct cgraph_node *orig_node;
363 for (orig_node = old_node; orig_node->clone_of; orig_node = orig_node->clone_of)
364 ;
365 for (arg = DECL_ARGUMENTS (orig_node->symbol.decl);
366 arg; arg = DECL_CHAIN (arg), oldi++)
367 {
368 if (bitmap_bit_p (old_node->clone.combined_args_to_skip, oldi))
369 {
370 bitmap_set_bit (new_args_to_skip, oldi);
371 continue;
372 }
373 if (bitmap_bit_p (args_to_skip, newi))
374 bitmap_set_bit (new_args_to_skip, oldi);
375 newi++;
376 }
377 new_node->clone.combined_args_to_skip = new_args_to_skip;
378 }
379 else
380 new_node->clone.combined_args_to_skip = args_to_skip;
381 new_node->symbol.externally_visible = 0;
382 new_node->local.local = 1;
383 new_node->lowered = true;
384
385 cgraph_call_node_duplication_hooks (old_node, new_node);
386
387
388 return new_node;
389}
390
391/* NODE is being removed from symbol table; see if its entry can be replaced by
392 other inline clone. */
393struct cgraph_node *
394cgraph_find_replacement_node (struct cgraph_node *node)
395{
396 struct cgraph_node *next_inline_clone, *replacement;
397
398 for (next_inline_clone = node->clones;
399 next_inline_clone
400 && next_inline_clone->symbol.decl != node->symbol.decl;
401 next_inline_clone = next_inline_clone->next_sibling_clone)
402 ;
403
404 /* If there is inline clone of the node being removed, we need
405 to put it into the position of removed node and reorganize all
406 other clones to be based on it. */
407 if (next_inline_clone)
408 {
409 struct cgraph_node *n;
410 struct cgraph_node *new_clones;
411
412 replacement = next_inline_clone;
413
414 /* Unlink inline clone from the list of clones of removed node. */
415 if (next_inline_clone->next_sibling_clone)
416 next_inline_clone->next_sibling_clone->prev_sibling_clone
417 = next_inline_clone->prev_sibling_clone;
418 if (next_inline_clone->prev_sibling_clone)
419 {
420 gcc_assert (node->clones != next_inline_clone);
421 next_inline_clone->prev_sibling_clone->next_sibling_clone
422 = next_inline_clone->next_sibling_clone;
423 }
424 else
425 {
426 gcc_assert (node->clones == next_inline_clone);
427 node->clones = next_inline_clone->next_sibling_clone;
428 }
429
430 new_clones = node->clones;
431 node->clones = NULL;
432
433 /* Copy clone info. */
434 next_inline_clone->clone = node->clone;
435
436 /* Now place it into clone tree at same level at NODE. */
437 next_inline_clone->clone_of = node->clone_of;
438 next_inline_clone->prev_sibling_clone = NULL;
439 next_inline_clone->next_sibling_clone = NULL;
440 if (node->clone_of)
441 {
442 if (node->clone_of->clones)
443 node->clone_of->clones->prev_sibling_clone = next_inline_clone;
444 next_inline_clone->next_sibling_clone = node->clone_of->clones;
445 node->clone_of->clones = next_inline_clone;
446 }
447
448 /* Merge the clone list. */
449 if (new_clones)
450 {
451 if (!next_inline_clone->clones)
452 next_inline_clone->clones = new_clones;
453 else
454 {
455 n = next_inline_clone->clones;
456 while (n->next_sibling_clone)
457 n = n->next_sibling_clone;
458 n->next_sibling_clone = new_clones;
459 new_clones->prev_sibling_clone = n;
460 }
461 }
462
463 /* Update clone_of pointers. */
464 n = new_clones;
465 while (n)
466 {
467 n->clone_of = next_inline_clone;
468 n = n->next_sibling_clone;
469 }
470 return replacement;
471 }
472 else
473 return NULL;
474}
475
476/* Like cgraph_set_call_stmt but walk the clone tree and update all
477 clones sharing the same function body. */
478
479void
480cgraph_set_call_stmt_including_clones (struct cgraph_node *orig,
481 gimple old_stmt, gimple new_stmt)
482{
483 struct cgraph_node *node;
484 struct cgraph_edge *edge = cgraph_edge (orig, old_stmt);
485
486 if (edge)
487 cgraph_set_call_stmt (edge, new_stmt);
488
489 node = orig->clones;
490 if (node)
491 while (node != orig)
492 {
493 struct cgraph_edge *edge = cgraph_edge (node, old_stmt);
494 if (edge)
495 cgraph_set_call_stmt (edge, new_stmt);
496 if (node->clones)
497 node = node->clones;
498 else if (node->next_sibling_clone)
499 node = node->next_sibling_clone;
500 else
501 {
502 while (node != orig && !node->next_sibling_clone)
503 node = node->clone_of;
504 if (node != orig)
505 node = node->next_sibling_clone;
506 }
507 }
508}
509
510/* Like cgraph_create_edge walk the clone tree and update all clones sharing
511 same function body. If clones already have edge for OLD_STMT; only
512 update the edge same way as cgraph_set_call_stmt_including_clones does.
513
514 TODO: COUNT and LOOP_DEPTH should be properly distributed based on relative
515 frequencies of the clones. */
516
517void
518cgraph_create_edge_including_clones (struct cgraph_node *orig,
519 struct cgraph_node *callee,
520 gimple old_stmt,
521 gimple stmt, gcov_type count,
522 int freq,
523 cgraph_inline_failed_t reason)
524{
525 struct cgraph_node *node;
526 struct cgraph_edge *edge;
527
528 if (!cgraph_edge (orig, stmt))
529 {
530 edge = cgraph_create_edge (orig, callee, stmt, count, freq);
531 edge->inline_failed = reason;
532 }
533
534 node = orig->clones;
535 if (node)
536 while (node != orig)
537 {
538 struct cgraph_edge *edge = cgraph_edge (node, old_stmt);
539
540 /* It is possible that clones already contain the edge while
541 master didn't. Either we promoted indirect call into direct
542 call in the clone or we are processing clones of unreachable
543 master where edges has been removed. */
544 if (edge)
545 cgraph_set_call_stmt (edge, stmt);
546 else if (!cgraph_edge (node, stmt))
547 {
548 edge = cgraph_create_edge (node, callee, stmt, count,
549 freq);
550 edge->inline_failed = reason;
551 }
552
553 if (node->clones)
554 node = node->clones;
555 else if (node->next_sibling_clone)
556 node = node->next_sibling_clone;
557 else
558 {
559 while (node != orig && !node->next_sibling_clone)
560 node = node->clone_of;
561 if (node != orig)
562 node = node->next_sibling_clone;
563 }
564 }
565}
566
567/* Remove the node from cgraph and all inline clones inlined into it.
568 Skip however removal of FORBIDDEN_NODE and return true if it needs to be
569 removed. This allows to call the function from outer loop walking clone
570 tree. */
571
572bool
573cgraph_remove_node_and_inline_clones (struct cgraph_node *node, struct cgraph_node *forbidden_node)
574{
575 struct cgraph_edge *e, *next;
576 bool found = false;
577
578 if (node == forbidden_node)
39f9719e
JH
579 {
580 cgraph_remove_edge (node->callers);
581 return true;
582 }
564fe867
JH
583 for (e = node->callees; e; e = next)
584 {
585 next = e->next_callee;
586 if (!e->inline_failed)
587 found |= cgraph_remove_node_and_inline_clones (e->callee, forbidden_node);
588 }
589 cgraph_remove_node (node);
590 return found;
591}
592
593/* The edges representing the callers of the NEW_VERSION node were
594 fixed by cgraph_function_versioning (), now the call_expr in their
595 respective tree code should be updated to call the NEW_VERSION. */
596
597static void
598update_call_expr (struct cgraph_node *new_version)
599{
600 struct cgraph_edge *e;
601
602 gcc_assert (new_version);
603
604 /* Update the call expr on the edges to call the new version. */
605 for (e = new_version->callers; e; e = e->next_caller)
606 {
607 struct function *inner_function = DECL_STRUCT_FUNCTION (e->caller->symbol.decl);
608 gimple_call_set_fndecl (e->call_stmt, new_version->symbol.decl);
609 maybe_clean_eh_stmt_fn (inner_function, e->call_stmt);
610 }
611}
612
613
614/* Create a new cgraph node which is the new version of
615 OLD_VERSION node. REDIRECT_CALLERS holds the callers
616 edges which should be redirected to point to
617 NEW_VERSION. ALL the callees edges of OLD_VERSION
618 are cloned to the new version node. Return the new
619 version node.
620
621 If non-NULL BLOCK_TO_COPY determine what basic blocks
622 was copied to prevent duplications of calls that are dead
623 in the clone. */
624
625struct cgraph_node *
626cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
627 tree new_decl,
9771b263 628 vec<cgraph_edge_p> redirect_callers,
564fe867
JH
629 bitmap bbs_to_copy)
630 {
631 struct cgraph_node *new_version;
632 struct cgraph_edge *e;
633 unsigned i;
634
635 gcc_assert (old_version);
636
637 new_version = cgraph_create_node (new_decl);
638
e70670cf
JH
639 new_version->symbol.analyzed = old_version->symbol.analyzed;
640 new_version->symbol.definition = old_version->symbol.definition;
564fe867
JH
641 new_version->local = old_version->local;
642 new_version->symbol.externally_visible = false;
e70670cf 643 new_version->local.local = new_version->symbol.definition;
564fe867
JH
644 new_version->global = old_version->global;
645 new_version->rtl = old_version->rtl;
646 new_version->count = old_version->count;
647
648 for (e = old_version->callees; e; e=e->next_callee)
649 if (!bbs_to_copy
650 || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index))
651 cgraph_clone_edge (e, new_version, e->call_stmt,
652 e->lto_stmt_uid, REG_BR_PROB_BASE,
653 CGRAPH_FREQ_BASE,
654 true);
655 for (e = old_version->indirect_calls; e; e=e->next_callee)
656 if (!bbs_to_copy
657 || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index))
658 cgraph_clone_edge (e, new_version, e->call_stmt,
659 e->lto_stmt_uid, REG_BR_PROB_BASE,
660 CGRAPH_FREQ_BASE,
661 true);
9771b263 662 FOR_EACH_VEC_ELT (redirect_callers, i, e)
564fe867
JH
663 {
664 /* Redirect calls to the old version node to point to its new
665 version. */
666 cgraph_redirect_edge_callee (e, new_version);
667 }
668
669 cgraph_call_node_duplication_hooks (old_version, new_version);
670
671 return new_version;
672 }
673
674/* Perform function versioning.
675 Function versioning includes copying of the tree and
676 a callgraph update (creating a new cgraph node and updating
677 its callees and callers).
678
679 REDIRECT_CALLERS varray includes the edges to be redirected
680 to the new version.
681
682 TREE_MAP is a mapping of tree nodes we want to replace with
683 new ones (according to results of prior analysis).
684 OLD_VERSION_NODE is the node that is versioned.
685
686 If non-NULL ARGS_TO_SKIP determine function parameters to remove
687 from new version.
688 If SKIP_RETURN is true, the new version will return void.
689 If non-NULL BLOCK_TO_COPY determine what basic blocks to copy.
690 If non_NULL NEW_ENTRY determine new entry BB of the clone.
691
692 Return the new version's cgraph node. */
693
694struct cgraph_node *
695cgraph_function_versioning (struct cgraph_node *old_version_node,
9771b263
DN
696 vec<cgraph_edge_p> redirect_callers,
697 vec<ipa_replace_map_p, va_gc> *tree_map,
564fe867
JH
698 bitmap args_to_skip,
699 bool skip_return,
700 bitmap bbs_to_copy,
701 basic_block new_entry_block,
702 const char *clone_name)
703{
704 tree old_decl = old_version_node->symbol.decl;
705 struct cgraph_node *new_version_node = NULL;
706 tree new_decl;
707
708 if (!tree_versionable_function_p (old_decl))
709 return NULL;
710
711 gcc_assert (old_version_node->local.can_change_signature || !args_to_skip);
712
713 /* Make a new FUNCTION_DECL tree node for the new version. */
714 if (!args_to_skip && !skip_return)
715 new_decl = copy_node (old_decl);
716 else
717 new_decl
718 = build_function_decl_skip_args (old_decl, args_to_skip, skip_return);
719
720 /* Generate a new name for the new version. */
721 DECL_NAME (new_decl) = clone_function_name (old_decl, clone_name);
722 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
723 SET_DECL_RTL (new_decl, NULL);
724
725 /* When the old decl was a con-/destructor make sure the clone isn't. */
726 DECL_STATIC_CONSTRUCTOR(new_decl) = 0;
727 DECL_STATIC_DESTRUCTOR(new_decl) = 0;
728
729 /* Create the new version's call-graph node.
730 and update the edges of the new node. */
731 new_version_node =
732 cgraph_copy_node_for_versioning (old_version_node, new_decl,
733 redirect_callers, bbs_to_copy);
734
735 /* Copy the OLD_VERSION_NODE function tree to the new version. */
736 tree_function_versioning (old_decl, new_decl, tree_map, false, args_to_skip,
737 skip_return, bbs_to_copy, new_entry_block);
738
739 /* Update the new version's properties.
740 Make The new version visible only within this translation unit. Make sure
741 that is not weak also.
742 ??? We cannot use COMDAT linkage because there is no
743 ABI support for this. */
744 symtab_make_decl_local (new_version_node->symbol.decl);
745 DECL_VIRTUAL_P (new_version_node->symbol.decl) = 0;
746 new_version_node->symbol.externally_visible = 0;
747 new_version_node->local.local = 1;
748 new_version_node->lowered = true;
702d8703
JH
749 /* Clones of global symbols or symbols with unique names are unique. */
750 if ((TREE_PUBLIC (old_decl)
751 && !DECL_EXTERNAL (old_decl)
752 && !DECL_WEAK (old_decl)
753 && !DECL_COMDAT (old_decl))
754 || in_lto_p)
755 new_version_node->symbol.unique_name = true;
564fe867
JH
756
757 /* Update the call_expr on the edges to call the new version node. */
758 update_call_expr (new_version_node);
759
760 cgraph_call_function_insertion_hooks (new_version_node);
761 return new_version_node;
762}
763
764/* Given virtual clone, turn it into actual clone. */
765
766static void
767cgraph_materialize_clone (struct cgraph_node *node)
768{
769 bitmap_obstack_initialize (NULL);
770 node->former_clone_of = node->clone_of->symbol.decl;
771 if (node->clone_of->former_clone_of)
772 node->former_clone_of = node->clone_of->former_clone_of;
773 /* Copy the OLD_VERSION_NODE function tree to the new version. */
774 tree_function_versioning (node->clone_of->symbol.decl, node->symbol.decl,
775 node->clone.tree_map, true,
776 node->clone.args_to_skip, false,
777 NULL, NULL);
778 if (cgraph_dump_file)
779 {
780 dump_function_to_file (node->clone_of->symbol.decl, cgraph_dump_file, dump_flags);
781 dump_function_to_file (node->symbol.decl, cgraph_dump_file, dump_flags);
782 }
783
784 /* Function is no longer clone. */
785 if (node->next_sibling_clone)
786 node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone;
787 if (node->prev_sibling_clone)
788 node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
789 else
790 node->clone_of->clones = node->next_sibling_clone;
791 node->next_sibling_clone = NULL;
792 node->prev_sibling_clone = NULL;
e70670cf 793 if (!node->clone_of->symbol.analyzed && !node->clone_of->clones)
564fe867
JH
794 {
795 cgraph_release_function_body (node->clone_of);
796 cgraph_node_remove_callees (node->clone_of);
797 ipa_remove_all_references (&node->clone_of->symbol.ref_list);
798 }
799 node->clone_of = NULL;
800 bitmap_obstack_release (NULL);
801}
802
803/* Once all functions from compilation unit are in memory, produce all clones
804 and update all calls. We might also do this on demand if we don't want to
805 bring all functions to memory prior compilation, but current WHOPR
806 implementation does that and it is is bit easier to keep everything right in
807 this order. */
808
809void
810cgraph_materialize_all_clones (void)
811{
812 struct cgraph_node *node;
813 bool stabilized = false;
814
815 if (cgraph_dump_file)
816 fprintf (cgraph_dump_file, "Materializing clones\n");
817#ifdef ENABLE_CHECKING
818 verify_cgraph ();
819#endif
820
821 /* We can also do topological order, but number of iterations should be
822 bounded by number of IPA passes since single IPA pass is probably not
823 going to create clones of clones it created itself. */
824 while (!stabilized)
825 {
826 stabilized = true;
827 FOR_EACH_FUNCTION (node)
828 {
829 if (node->clone_of && node->symbol.decl != node->clone_of->symbol.decl
830 && !gimple_has_body_p (node->symbol.decl))
831 {
832 if (gimple_has_body_p (node->clone_of->symbol.decl))
833 {
834 if (cgraph_dump_file)
835 {
836 fprintf (cgraph_dump_file, "cloning %s to %s\n",
837 xstrdup (cgraph_node_name (node->clone_of)),
838 xstrdup (cgraph_node_name (node)));
839 if (node->clone.tree_map)
840 {
841 unsigned int i;
842 fprintf (cgraph_dump_file, " replace map: ");
9771b263
DN
843 for (i = 0;
844 i < vec_safe_length (node->clone.tree_map);
845 i++)
564fe867
JH
846 {
847 struct ipa_replace_map *replace_info;
9771b263 848 replace_info = (*node->clone.tree_map)[i];
564fe867
JH
849 print_generic_expr (cgraph_dump_file, replace_info->old_tree, 0);
850 fprintf (cgraph_dump_file, " -> ");
851 print_generic_expr (cgraph_dump_file, replace_info->new_tree, 0);
852 fprintf (cgraph_dump_file, "%s%s;",
853 replace_info->replace_p ? "(replace)":"",
854 replace_info->ref_p ? "(ref)":"");
855 }
856 fprintf (cgraph_dump_file, "\n");
857 }
858 if (node->clone.args_to_skip)
859 {
860 fprintf (cgraph_dump_file, " args_to_skip: ");
861 dump_bitmap (cgraph_dump_file, node->clone.args_to_skip);
862 }
863 if (node->clone.args_to_skip)
864 {
865 fprintf (cgraph_dump_file, " combined_args_to_skip:");
866 dump_bitmap (cgraph_dump_file, node->clone.combined_args_to_skip);
867 }
868 }
869 cgraph_materialize_clone (node);
870 stabilized = false;
871 }
872 }
873 }
874 }
875 FOR_EACH_FUNCTION (node)
e70670cf 876 if (!node->symbol.analyzed && node->callees)
564fe867
JH
877 cgraph_node_remove_callees (node);
878 if (cgraph_dump_file)
879 fprintf (cgraph_dump_file, "Materialization Call site updates done.\n");
880#ifdef ENABLE_CHECKING
881 verify_cgraph ();
882#endif
04142cc3 883 symtab_remove_unreachable_nodes (false, cgraph_dump_file);
564fe867
JH
884}
885
886#include "gt-cgraphclones.h"
This page took 0.398906 seconds and 5 git commands to generate.