]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/cgraphclones.c
2015-06-04 Andrew MacLeod <amacleod@redhat.com>
[thirdparty/gcc.git] / gcc / cgraphclones.c
CommitLineData
c02159a7 1/* Callgraph clones
d353bf18 2 Copyright (C) 2003-2015 Free Software Foundation, Inc.
c02159a7 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"
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
123cgraph_edge *
1a91d914 124cgraph_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
191static tree
192build_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
247static tree
248build_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
283static void
284set_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
304static cgraph_node *
2e1475da 305duplicate_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
386void
fe3c9f1e 387cgraph_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
399void
400cgraph_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 436cgraph_node *
c28f0245 437cgraph_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 536static 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 541tree
a73afd90 542clone_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
563tree
564clone_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 577cgraph_node *
415d1b9a 578cgraph_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. */
654cgraph_node *
655cgraph_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
743void
1a91d914 744cgraph_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
798void
35ee1c66 799cgraph_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
851bool
415d1b9a 852cgraph_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
876static void
35ee1c66 877update_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 904cgraph_node *
905cgraph_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 970cgraph_node *
971cgraph_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
1043static void
35ee1c66 1044cgraph_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
1087void
35ee1c66 1088symbol_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"