Update my e-mail address for new employer.
[official-gcc.git] / gcc / cgraphunit.c
blob7a043d0edea0a5fa1eaee7d9c3144c28ed9699f3
1 /* Callgraph based interprocedural optimizations.
2 Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
3 Contributed by Jan Hubicka
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to the Free
19 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301, USA. */
22 /* This module implements main driver of compilation process as well as
23 few basic interprocedural optimizers.
25 The main scope of this file is to act as an interface in between
26 tree based frontends and the backend (and middle end)
28 The front-end is supposed to use following functionality:
30 - cgraph_finalize_function
32 This function is called once front-end has parsed whole body of function
33 and it is certain that the function body nor the declaration will change.
35 (There is one exception needed for implementing GCC extern inline
36 function.)
38 - varpool_finalize_variable
40 This function has same behavior as the above but is used for static
41 variables.
43 - cgraph_finalize_compilation_unit
45 This function is called once (source level) compilation unit is finalized
46 and it will no longer change.
48 In the unit-at-a-time the call-graph construction and local function
49 analysis takes place here. Bodies of unreachable functions are released
50 to conserve memory usage.
52 The function can be called multiple times when multiple source level
53 compilation units are combined (such as in C frontend)
55 - cgraph_optimize
57 In this unit-at-a-time compilation the intra procedural analysis takes
58 place here. In particular the static functions whose address is never
59 taken are marked as local. Backend can then use this information to
60 modify calling conventions, do better inlining or similar optimizations.
62 - cgraph_mark_needed_node
63 - varpool_mark_needed_node
65 When function or variable is referenced by some hidden way the call-graph
66 data structure must be updated accordingly by this function.
67 There should be little need to call this function and all the references
68 should be made explicit to cgraph code. At present these functions are
69 used by C++ frontend to explicitly mark the keyed methods.
71 - analyze_expr callback
73 This function is responsible for lowering tree nodes not understood by
74 generic code into understandable ones or alternatively marking
75 callgraph and varpool nodes referenced by the as needed.
77 ??? On the tree-ssa genericizing should take place here and we will avoid
78 need for these hooks (replacing them by genericizing hook)
80 - expand_function callback
82 This function is used to expand function and pass it into RTL back-end.
83 Front-end should not make any assumptions about when this function can be
84 called. In particular cgraph_assemble_pending_functions,
85 varpool_assemble_pending_variables, cgraph_finalize_function,
86 varpool_finalize_function, cgraph_optimize can cause arbitrarily
87 previously finalized functions to be expanded.
89 We implement two compilation modes.
91 - unit-at-a-time: In this mode analyzing of all functions is deferred
92 to cgraph_finalize_compilation_unit and expansion into cgraph_optimize.
94 In cgraph_finalize_compilation_unit the reachable functions are
95 analyzed. During analysis the call-graph edges from reachable
96 functions are constructed and their destinations are marked as
97 reachable. References to functions and variables are discovered too
98 and variables found to be needed output to the assembly file. Via
99 mark_referenced call in assemble_variable functions referenced by
100 static variables are noticed too.
102 The intra-procedural information is produced and its existence
103 indicated by global_info_ready. Once this flag is set it is impossible
104 to change function from !reachable to reachable and thus
105 assemble_variable no longer call mark_referenced.
107 Finally the call-graph is topologically sorted and all reachable functions
108 that has not been completely inlined or are not external are output.
110 ??? It is possible that reference to function or variable is optimized
111 out. We can not deal with this nicely because topological order is not
112 suitable for it. For tree-ssa we may consider another pass doing
113 optimization and re-discovering reachable functions.
115 ??? Reorganize code so variables are output very last and only if they
116 really has been referenced by produced code, so we catch more cases
117 where reference has been optimized out.
119 - non-unit-at-a-time
121 All functions are variables are output as early as possible to conserve
122 memory consumption. This may or may not result in less memory used but
123 it is still needed for some legacy code that rely on particular ordering
124 of things output from the compiler.
126 Varpool data structures are not used and variables are output directly.
128 Functions are output early using call of
129 cgraph_assemble_pending_function from cgraph_finalize_function. The
130 decision on whether function is needed is made more conservative so
131 uninlininable static functions are needed too. During the call-graph
132 construction the edge destinations are not marked as reachable and it
133 is completely relied upn assemble_variable to mark them. */
136 #include "config.h"
137 #include "system.h"
138 #include "coretypes.h"
139 #include "tm.h"
140 #include "tree.h"
141 #include "rtl.h"
142 #include "tree-flow.h"
143 #include "tree-inline.h"
144 #include "langhooks.h"
145 #include "pointer-set.h"
146 #include "toplev.h"
147 #include "flags.h"
148 #include "ggc.h"
149 #include "debug.h"
150 #include "target.h"
151 #include "cgraph.h"
152 #include "diagnostic.h"
153 #include "timevar.h"
154 #include "params.h"
155 #include "fibheap.h"
156 #include "c-common.h"
157 #include "intl.h"
158 #include "function.h"
159 #include "ipa-prop.h"
160 #include "tree-gimple.h"
161 #include "tree-pass.h"
162 #include "output.h"
164 static void cgraph_expand_all_functions (void);
165 static void cgraph_mark_functions_to_output (void);
166 static void cgraph_expand_function (struct cgraph_node *);
167 static void cgraph_output_pending_asms (void);
169 static FILE *cgraph_dump_file;
171 static GTY (()) tree static_ctors;
172 static GTY (()) tree static_dtors;
174 /* When target does not have ctors and dtors, we call all constructor
175 and destructor by special initialization/destruction functio
176 recognized by collect2.
178 When we are going to build this function, collect all constructors and
179 destructors and turn them into normal functions. */
181 static void
182 record_cdtor_fn (tree fndecl)
184 if (targetm.have_ctors_dtors)
185 return;
187 if (DECL_STATIC_CONSTRUCTOR (fndecl))
189 static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
190 DECL_STATIC_CONSTRUCTOR (fndecl) = 0;
191 cgraph_mark_reachable_node (cgraph_node (fndecl));
193 if (DECL_STATIC_DESTRUCTOR (fndecl))
195 static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
196 DECL_STATIC_DESTRUCTOR (fndecl) = 0;
197 cgraph_mark_reachable_node (cgraph_node (fndecl));
201 /* Synthesize a function which calls all the global ctors or global
202 dtors in this file. This is only used for targets which do not
203 support .ctors/.dtors sections. */
204 static void
205 build_cdtor (int method_type, tree cdtors)
207 tree body = 0;
209 if (!cdtors)
210 return;
212 for (; cdtors; cdtors = TREE_CHAIN (cdtors))
213 append_to_statement_list (build_function_call_expr (TREE_VALUE (cdtors), 0),
214 &body);
216 cgraph_build_static_cdtor (method_type, body, DEFAULT_INIT_PRIORITY);
219 /* Generate functions to call static constructors and destructors
220 for targets that do not support .ctors/.dtors sections. These
221 functions have magic names which are detected by collect2. */
223 static void
224 cgraph_build_cdtor_fns (void)
226 if (!targetm.have_ctors_dtors)
228 build_cdtor ('I', static_ctors);
229 static_ctors = NULL_TREE;
230 build_cdtor ('D', static_dtors);
231 static_dtors = NULL_TREE;
233 else
235 gcc_assert (!static_ctors);
236 gcc_assert (!static_dtors);
240 /* Determine if function DECL is needed. That is, visible to something
241 either outside this translation unit, something magic in the system
242 configury, or (if not doing unit-at-a-time) to something we havn't
243 seen yet. */
245 static bool
246 decide_is_function_needed (struct cgraph_node *node, tree decl)
248 tree origin;
249 if (MAIN_NAME_P (DECL_NAME (decl))
250 && TREE_PUBLIC (decl))
252 node->local.externally_visible = true;
253 return true;
256 /* If the user told us it is used, then it must be so. */
257 if (node->local.externally_visible)
258 return true;
260 if (!flag_unit_at_a_time && lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
261 return true;
263 /* ??? If the assembler name is set by hand, it is possible to assemble
264 the name later after finalizing the function and the fact is noticed
265 in assemble_name then. This is arguably a bug. */
266 if (DECL_ASSEMBLER_NAME_SET_P (decl)
267 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
268 return true;
270 /* With -fkeep-inline-functions we are keeping all inline functions except
271 for extern inline ones. */
272 if (flag_keep_inline_functions
273 && DECL_DECLARED_INLINE_P (decl)
274 && !DECL_EXTERNAL (decl)
275 && !lookup_attribute ("always_inline", DECL_ATTRIBUTES (decl)))
276 return true;
278 /* If we decided it was needed before, but at the time we didn't have
279 the body of the function available, then it's still needed. We have
280 to go back and re-check its dependencies now. */
281 if (node->needed)
282 return true;
284 /* Externally visible functions must be output. The exception is
285 COMDAT functions that must be output only when they are needed.
287 When not optimizing, also output the static functions. (see
288 PR24561), but don't do so for always_inline functions, functions
289 declared inline and nested functions. These was optimized out
290 in the original implementation and it is unclear whether we want
291 to change the behavior here. */
292 if (((TREE_PUBLIC (decl)
293 || (!optimize && !node->local.disregard_inline_limits
294 && !DECL_DECLARED_INLINE_P (decl)
295 && !node->origin))
296 && !flag_whole_program)
297 && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
298 return true;
300 /* Constructors and destructors are reachable from the runtime by
301 some mechanism. */
302 if (DECL_STATIC_CONSTRUCTOR (decl) || DECL_STATIC_DESTRUCTOR (decl))
303 return true;
305 if (flag_unit_at_a_time)
306 return false;
308 /* If not doing unit at a time, then we'll only defer this function
309 if its marked for inlining. Otherwise we want to emit it now. */
311 /* "extern inline" functions are never output locally. */
312 if (DECL_EXTERNAL (decl))
313 return false;
314 /* Nested functions of extern inline function shall not be emit unless
315 we inlined the origin. */
316 for (origin = decl_function_context (decl); origin;
317 origin = decl_function_context (origin))
318 if (DECL_EXTERNAL (origin))
319 return false;
320 /* We want to emit COMDAT functions only when absolutely necessary. */
321 if (DECL_COMDAT (decl))
322 return false;
323 if (!DECL_INLINE (decl)
324 || (!node->local.disregard_inline_limits
325 /* When declared inline, defer even the uninlinable functions.
326 This allows them to be eliminated when unused. */
327 && !DECL_DECLARED_INLINE_P (decl)
328 && (!node->local.inlinable || !cgraph_default_inline_p (node, NULL))))
329 return true;
331 return false;
334 /* Process CGRAPH_NEW_FUNCTIONS and perform actions necessary to add these
335 functions into callgraph in a way so they look like ordinary reachable
336 functions inserted into callgraph already at construction time. */
338 bool
339 cgraph_process_new_functions (void)
341 bool output = false;
342 tree fndecl;
343 struct cgraph_node *node;
345 /* Note that this queue may grow as its being processed, as the new
346 functions may generate new ones. */
347 while (cgraph_new_nodes)
349 node = cgraph_new_nodes;
350 fndecl = node->decl;
351 cgraph_new_nodes = cgraph_new_nodes->next_needed;
352 switch (cgraph_state)
354 case CGRAPH_STATE_CONSTRUCTION:
355 /* At construction time we just need to finalize function and move
356 it into reachable functions list. */
358 node->next_needed = NULL;
359 node->needed = node->reachable = false;
360 cgraph_finalize_function (fndecl, false);
361 cgraph_mark_reachable_node (node);
362 output = true;
363 break;
365 case CGRAPH_STATE_IPA:
366 case CGRAPH_STATE_IPA_SSA:
367 /* When IPA optimization already started, do all essential
368 transformations that has been already performed on the whole
369 cgraph but not on this function. */
371 tree_register_cfg_hooks ();
372 if (!node->analyzed)
373 cgraph_analyze_function (node);
374 push_cfun (DECL_STRUCT_FUNCTION (fndecl));
375 current_function_decl = fndecl;
376 node->local.inlinable = tree_inlinable_function_p (fndecl);
377 node->local.self_insns = estimate_num_insns (fndecl,
378 &eni_inlining_weights);
379 node->local.disregard_inline_limits
380 = lang_hooks.tree_inlining.disregard_inline_limits (fndecl);
381 /* Inlining characteristics are maintained by the
382 cgraph_mark_inline. */
383 node->global.insns = node->local.self_insns;
384 if (flag_really_no_inline && !node->local.disregard_inline_limits)
385 node->local.inlinable = 0;
386 if ((cgraph_state == CGRAPH_STATE_IPA_SSA
387 && !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
388 /* When not optimizing, be sure we run early local passes anyway
389 to expand OMP. */
390 || !optimize)
391 execute_pass_list (pass_early_local_passes.sub);
392 free_dominance_info (CDI_POST_DOMINATORS);
393 free_dominance_info (CDI_DOMINATORS);
394 pop_cfun ();
395 current_function_decl = NULL;
396 break;
398 case CGRAPH_STATE_EXPANSION:
399 /* Functions created during expansion shall be compiled
400 directly. */
401 node->output = 0;
402 cgraph_expand_function (node);
403 break;
405 default:
406 gcc_unreachable ();
407 break;
410 return output;
413 /* When not doing unit-at-a-time, output all functions enqueued.
414 Return true when such a functions were found. */
416 static bool
417 cgraph_assemble_pending_functions (void)
419 bool output = false;
421 if (flag_unit_at_a_time)
422 return false;
424 cgraph_output_pending_asms ();
426 while (cgraph_nodes_queue)
428 struct cgraph_node *n = cgraph_nodes_queue;
430 cgraph_nodes_queue = cgraph_nodes_queue->next_needed;
431 n->next_needed = NULL;
432 if (!n->global.inlined_to
433 && !n->alias
434 && !DECL_EXTERNAL (n->decl))
436 cgraph_expand_function (n);
437 output = true;
439 output |= cgraph_process_new_functions ();
442 return output;
446 /* As an GCC extension we allow redefinition of the function. The
447 semantics when both copies of bodies differ is not well defined.
448 We replace the old body with new body so in unit at a time mode
449 we always use new body, while in normal mode we may end up with
450 old body inlined into some functions and new body expanded and
451 inlined in others.
453 ??? It may make more sense to use one body for inlining and other
454 body for expanding the function but this is difficult to do. */
456 static void
457 cgraph_reset_node (struct cgraph_node *node)
459 /* If node->output is set, then this is a unit-at-a-time compilation
460 and we have already begun whole-unit analysis. This is *not*
461 testing for whether we've already emitted the function. That
462 case can be sort-of legitimately seen with real function
463 redefinition errors. I would argue that the front end should
464 never present us with such a case, but don't enforce that for now. */
465 gcc_assert (!node->output);
467 /* Reset our data structures so we can analyze the function again. */
468 memset (&node->local, 0, sizeof (node->local));
469 memset (&node->global, 0, sizeof (node->global));
470 memset (&node->rtl, 0, sizeof (node->rtl));
471 node->analyzed = false;
472 node->local.redefined_extern_inline = true;
473 node->local.finalized = false;
475 if (!flag_unit_at_a_time)
477 struct cgraph_node *n, *next;
479 for (n = cgraph_nodes; n; n = next)
481 next = n->next;
482 if (n->global.inlined_to == node)
483 cgraph_remove_node (n);
487 cgraph_node_remove_callees (node);
489 /* We may need to re-queue the node for assembling in case
490 we already proceeded it and ignored as not needed. */
491 if (node->reachable && !flag_unit_at_a_time)
493 struct cgraph_node *n;
495 for (n = cgraph_nodes_queue; n; n = n->next_needed)
496 if (n == node)
497 break;
498 if (!n)
499 node->reachable = 0;
503 static void
504 cgraph_lower_function (struct cgraph_node *node)
506 if (node->lowered)
507 return;
508 tree_lowering_passes (node->decl);
509 node->lowered = true;
512 /* DECL has been parsed. Take it, queue it, compile it at the whim of the
513 logic in effect. If NESTED is true, then our caller cannot stand to have
514 the garbage collector run at the moment. We would need to either create
515 a new GC context, or just not compile right now. */
517 void
518 cgraph_finalize_function (tree decl, bool nested)
520 struct cgraph_node *node = cgraph_node (decl);
522 if (node->local.finalized)
523 cgraph_reset_node (node);
525 node->pid = cgraph_max_pid ++;
526 notice_global_symbol (decl);
527 node->decl = decl;
528 node->local.finalized = true;
529 node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL;
530 record_cdtor_fn (node->decl);
531 if (node->nested)
532 lower_nested_functions (decl);
533 gcc_assert (!node->nested);
535 /* If not unit at a time, then we need to create the call graph
536 now, so that called functions can be queued and emitted now. */
537 if (!flag_unit_at_a_time)
538 cgraph_analyze_function (node);
540 if (decide_is_function_needed (node, decl))
541 cgraph_mark_needed_node (node);
543 /* Since we reclaim unreachable nodes at the end of every language
544 level unit, we need to be conservative about possible entry points
545 there. */
546 if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)))
547 cgraph_mark_reachable_node (node);
549 /* If not unit at a time, go ahead and emit everything we've found
550 to be reachable at this time. */
551 if (!nested)
553 if (!cgraph_assemble_pending_functions ())
554 ggc_collect ();
557 /* If we've not yet emitted decl, tell the debug info about it. */
558 if (!TREE_ASM_WRITTEN (decl))
559 (*debug_hooks->deferred_inline_function) (decl);
561 /* Possibly warn about unused parameters. */
562 if (warn_unused_parameter)
563 do_warn_unused_parameter (decl);
566 /* Verify cgraph nodes of given cgraph node. */
567 void
568 verify_cgraph_node (struct cgraph_node *node)
570 struct cgraph_edge *e;
571 struct cgraph_node *main_clone;
572 struct function *this_cfun = DECL_STRUCT_FUNCTION (node->decl);
573 basic_block this_block;
574 block_stmt_iterator bsi;
575 bool error_found = false;
577 if (errorcount || sorrycount)
578 return;
580 timevar_push (TV_CGRAPH_VERIFY);
581 for (e = node->callees; e; e = e->next_callee)
582 if (e->aux)
584 error ("aux field set for edge %s->%s",
585 cgraph_node_name (e->caller), cgraph_node_name (e->callee));
586 error_found = true;
588 if (node->count < 0)
590 error ("Execution count is negative");
591 error_found = true;
593 for (e = node->callers; e; e = e->next_caller)
595 if (e->count < 0)
597 error ("caller edge count is negative");
598 error_found = true;
600 if (e->frequency < 0)
602 error ("caller edge frequency is negative");
603 error_found = true;
605 if (e->frequency > CGRAPH_FREQ_MAX)
607 error ("caller edge frequency is too large");
608 error_found = true;
610 if (!e->inline_failed)
612 if (node->global.inlined_to
613 != (e->caller->global.inlined_to
614 ? e->caller->global.inlined_to : e->caller))
616 error ("inlined_to pointer is wrong");
617 error_found = true;
619 if (node->callers->next_caller)
621 error ("multiple inline callers");
622 error_found = true;
625 else
626 if (node->global.inlined_to)
628 error ("inlined_to pointer set for noninline callers");
629 error_found = true;
632 if (!node->callers && node->global.inlined_to)
634 error ("inlined_to pointer is set but no predecessors found");
635 error_found = true;
637 if (node->global.inlined_to == node)
639 error ("inlined_to pointer refers to itself");
640 error_found = true;
643 for (main_clone = cgraph_node (node->decl); main_clone;
644 main_clone = main_clone->next_clone)
645 if (main_clone == node)
646 break;
647 if (!cgraph_node (node->decl))
649 error ("node not found in cgraph_hash");
650 error_found = true;
653 if (node->analyzed
654 && DECL_SAVED_TREE (node->decl) && !TREE_ASM_WRITTEN (node->decl)
655 && (!DECL_EXTERNAL (node->decl) || node->global.inlined_to))
657 if (this_cfun->cfg)
659 /* The nodes we're interested in are never shared, so walk
660 the tree ignoring duplicates. */
661 struct pointer_set_t *visited_nodes = pointer_set_create ();
662 /* Reach the trees by walking over the CFG, and note the
663 enclosing basic-blocks in the call edges. */
664 FOR_EACH_BB_FN (this_block, this_cfun)
665 for (bsi = bsi_start (this_block); !bsi_end_p (bsi); bsi_next (&bsi))
667 tree stmt = bsi_stmt (bsi);
668 tree call = get_call_expr_in (stmt);
669 tree decl;
670 if (call && (decl = get_callee_fndecl (call)))
672 struct cgraph_edge *e = cgraph_edge (node, stmt);
673 if (e)
675 if (e->aux)
677 error ("shared call_stmt:");
678 debug_generic_stmt (stmt);
679 error_found = true;
681 if (e->callee->decl != cgraph_node (decl)->decl
682 && e->inline_failed)
684 error ("edge points to wrong declaration:");
685 debug_tree (e->callee->decl);
686 fprintf (stderr," Instead of:");
687 debug_tree (decl);
689 e->aux = (void *)1;
691 else
693 error ("missing callgraph edge for call stmt:");
694 debug_generic_stmt (stmt);
695 error_found = true;
699 pointer_set_destroy (visited_nodes);
701 else
702 /* No CFG available?! */
703 gcc_unreachable ();
705 for (e = node->callees; e; e = e->next_callee)
707 if (!e->aux)
709 error ("edge %s->%s has no corresponding call_stmt",
710 cgraph_node_name (e->caller),
711 cgraph_node_name (e->callee));
712 debug_generic_stmt (e->call_stmt);
713 error_found = true;
715 e->aux = 0;
718 if (error_found)
720 dump_cgraph_node (stderr, node);
721 internal_error ("verify_cgraph_node failed");
723 timevar_pop (TV_CGRAPH_VERIFY);
726 /* Verify whole cgraph structure. */
727 void
728 verify_cgraph (void)
730 struct cgraph_node *node;
732 if (sorrycount || errorcount)
733 return;
735 for (node = cgraph_nodes; node; node = node->next)
736 verify_cgraph_node (node);
739 /* Output all asm statements we have stored up to be output. */
741 static void
742 cgraph_output_pending_asms (void)
744 struct cgraph_asm_node *can;
746 if (errorcount || sorrycount)
747 return;
749 for (can = cgraph_asm_nodes; can; can = can->next)
750 assemble_asm (can->asm_str);
751 cgraph_asm_nodes = NULL;
754 /* Analyze the function scheduled to be output. */
755 void
756 cgraph_analyze_function (struct cgraph_node *node)
758 tree decl = node->decl;
760 current_function_decl = decl;
761 push_cfun (DECL_STRUCT_FUNCTION (decl));
762 cgraph_lower_function (node);
764 node->local.estimated_self_stack_size = estimated_stack_frame_size ();
765 node->global.estimated_stack_size = node->local.estimated_self_stack_size;
766 node->global.stack_frame_offset = 0;
767 node->local.inlinable = tree_inlinable_function_p (decl);
768 if (!flag_unit_at_a_time)
769 node->local.self_insns = estimate_num_insns (decl, &eni_inlining_weights);
770 if (node->local.inlinable)
771 node->local.disregard_inline_limits
772 = lang_hooks.tree_inlining.disregard_inline_limits (decl);
773 if (flag_really_no_inline && !node->local.disregard_inline_limits)
774 node->local.inlinable = 0;
775 /* Inlining characteristics are maintained by the cgraph_mark_inline. */
776 node->global.insns = node->local.self_insns;
777 if (!flag_unit_at_a_time)
779 bitmap_obstack_initialize (NULL);
780 tree_register_cfg_hooks ();
781 execute_pass_list (pass_early_local_passes.sub);
782 free_dominance_info (CDI_POST_DOMINATORS);
783 free_dominance_info (CDI_DOMINATORS);
784 bitmap_obstack_release (NULL);
787 node->analyzed = true;
788 pop_cfun ();
789 current_function_decl = NULL;
792 /* Look for externally_visible and used attributes and mark cgraph nodes
793 accordingly.
795 We cannot mark the nodes at the point the attributes are processed (in
796 handle_*_attribute) because the copy of the declarations available at that
797 point may not be canonical. For example, in:
799 void f();
800 void f() __attribute__((used));
802 the declaration we see in handle_used_attribute will be the second
803 declaration -- but the front end will subsequently merge that declaration
804 with the original declaration and discard the second declaration.
806 Furthermore, we can't mark these nodes in cgraph_finalize_function because:
808 void f() {}
809 void f() __attribute__((externally_visible));
811 is valid.
813 So, we walk the nodes at the end of the translation unit, applying the
814 attributes at that point. */
816 static void
817 process_function_and_variable_attributes (struct cgraph_node *first,
818 struct varpool_node *first_var)
820 struct cgraph_node *node;
821 struct varpool_node *vnode;
823 for (node = cgraph_nodes; node != first; node = node->next)
825 tree decl = node->decl;
826 if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
828 mark_decl_referenced (decl);
829 if (node->local.finalized)
830 cgraph_mark_needed_node (node);
832 if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
834 if (! TREE_PUBLIC (node->decl))
835 warning (OPT_Wattributes,
836 "%J%<externally_visible%> attribute have effect only on public objects",
837 node->decl);
838 else
840 if (node->local.finalized)
841 cgraph_mark_needed_node (node);
842 node->local.externally_visible = true;
846 for (vnode = varpool_nodes; vnode != first_var; vnode = vnode->next)
848 tree decl = vnode->decl;
849 if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
851 mark_decl_referenced (decl);
852 if (vnode->finalized)
853 varpool_mark_needed_node (vnode);
855 if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
857 if (! TREE_PUBLIC (vnode->decl))
858 warning (OPT_Wattributes,
859 "%J%<externally_visible%> attribute have effect only on public objects",
860 vnode->decl);
861 else
863 if (vnode->finalized)
864 varpool_mark_needed_node (vnode);
865 vnode->externally_visible = true;
871 /* Process CGRAPH_NODES_NEEDED queue, analyze each function (and transitively
872 each reachable functions) and build cgraph.
873 The function can be called multiple times after inserting new nodes
874 into beginning of queue. Just the new part of queue is re-scanned then. */
876 static void
877 cgraph_analyze_functions (void)
879 /* Keep track of already processed nodes when called multiple times for
880 intermodule optimization. */
881 static struct cgraph_node *first_analyzed;
882 struct cgraph_node *first_processed = first_analyzed;
883 static struct varpool_node *first_analyzed_var;
884 struct cgraph_node *node, *next;
886 process_function_and_variable_attributes (first_processed,
887 first_analyzed_var);
888 first_processed = cgraph_nodes;
889 first_analyzed_var = varpool_nodes;
890 varpool_analyze_pending_decls ();
891 if (cgraph_dump_file)
893 fprintf (cgraph_dump_file, "Initial entry points:");
894 for (node = cgraph_nodes; node != first_analyzed; node = node->next)
895 if (node->needed && DECL_SAVED_TREE (node->decl))
896 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
897 fprintf (cgraph_dump_file, "\n");
899 cgraph_process_new_functions ();
901 /* Propagate reachability flag and lower representation of all reachable
902 functions. In the future, lowering will introduce new functions and
903 new entry points on the way (by template instantiation and virtual
904 method table generation for instance). */
905 while (cgraph_nodes_queue)
907 struct cgraph_edge *edge;
908 tree decl = cgraph_nodes_queue->decl;
910 node = cgraph_nodes_queue;
911 cgraph_nodes_queue = cgraph_nodes_queue->next_needed;
912 node->next_needed = NULL;
914 /* ??? It is possible to create extern inline function and later using
915 weak alias attribute to kill its body. See
916 gcc.c-torture/compile/20011119-1.c */
917 if (!DECL_SAVED_TREE (decl))
919 cgraph_reset_node (node);
920 continue;
923 gcc_assert (!node->analyzed && node->reachable);
924 gcc_assert (DECL_SAVED_TREE (decl));
926 cgraph_analyze_function (node);
928 for (edge = node->callees; edge; edge = edge->next_callee)
929 if (!edge->callee->reachable)
930 cgraph_mark_reachable_node (edge->callee);
932 /* We finalize local static variables during constructing callgraph
933 edges. Process their attributes too. */
934 process_function_and_variable_attributes (first_processed,
935 first_analyzed_var);
936 first_processed = cgraph_nodes;
937 first_analyzed_var = varpool_nodes;
938 varpool_analyze_pending_decls ();
939 cgraph_process_new_functions ();
942 /* Collect entry points to the unit. */
943 if (cgraph_dump_file)
945 fprintf (cgraph_dump_file, "Unit entry points:");
946 for (node = cgraph_nodes; node != first_analyzed; node = node->next)
947 if (node->needed && DECL_SAVED_TREE (node->decl))
948 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
949 fprintf (cgraph_dump_file, "\n\nInitial ");
950 dump_cgraph (cgraph_dump_file);
953 if (cgraph_dump_file)
954 fprintf (cgraph_dump_file, "\nReclaiming functions:");
956 for (node = cgraph_nodes; node != first_analyzed; node = next)
958 tree decl = node->decl;
959 next = node->next;
961 if (node->local.finalized && !DECL_SAVED_TREE (decl))
962 cgraph_reset_node (node);
964 if (!node->reachable && DECL_SAVED_TREE (decl))
966 if (cgraph_dump_file)
967 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
968 cgraph_remove_node (node);
969 continue;
971 else
972 node->next_needed = NULL;
973 gcc_assert (!node->local.finalized || DECL_SAVED_TREE (decl));
974 gcc_assert (node->analyzed == node->local.finalized);
976 if (cgraph_dump_file)
978 fprintf (cgraph_dump_file, "\n\nReclaimed ");
979 dump_cgraph (cgraph_dump_file);
981 first_analyzed = cgraph_nodes;
982 ggc_collect ();
985 /* Analyze the whole compilation unit once it is parsed completely. */
987 void
988 cgraph_finalize_compilation_unit (void)
990 if (errorcount || sorrycount)
991 return;
993 finish_aliases_1 ();
995 if (!flag_unit_at_a_time)
997 cgraph_output_pending_asms ();
998 cgraph_assemble_pending_functions ();
999 varpool_output_debug_info ();
1000 return;
1003 if (!quiet_flag)
1005 fprintf (stderr, "\nAnalyzing compilation unit\n");
1006 fflush (stderr);
1009 timevar_push (TV_CGRAPH);
1010 cgraph_analyze_functions ();
1011 timevar_pop (TV_CGRAPH);
1013 /* Figure out what functions we want to assemble. */
1015 static void
1016 cgraph_mark_functions_to_output (void)
1018 struct cgraph_node *node;
1020 for (node = cgraph_nodes; node; node = node->next)
1022 tree decl = node->decl;
1023 struct cgraph_edge *e;
1025 gcc_assert (!node->output);
1027 for (e = node->callers; e; e = e->next_caller)
1028 if (e->inline_failed)
1029 break;
1031 /* We need to output all local functions that are used and not
1032 always inlined, as well as those that are reachable from
1033 outside the current compilation unit. */
1034 if (DECL_SAVED_TREE (decl)
1035 && !node->global.inlined_to
1036 && (node->needed
1037 || (e && node->reachable))
1038 && !TREE_ASM_WRITTEN (decl)
1039 && !DECL_EXTERNAL (decl))
1040 node->output = 1;
1041 else
1043 /* We should've reclaimed all functions that are not needed. */
1044 #ifdef ENABLE_CHECKING
1045 if (!node->global.inlined_to && DECL_SAVED_TREE (decl)
1046 && !DECL_EXTERNAL (decl))
1048 dump_cgraph_node (stderr, node);
1049 internal_error ("failed to reclaim unneeded function");
1051 #endif
1052 gcc_assert (node->global.inlined_to || !DECL_SAVED_TREE (decl)
1053 || DECL_EXTERNAL (decl));
1060 /* Expand function specified by NODE. */
1062 static void
1063 cgraph_expand_function (struct cgraph_node *node)
1065 enum debug_info_type save_write_symbols = NO_DEBUG;
1066 const struct gcc_debug_hooks *save_debug_hooks = NULL;
1067 tree decl = node->decl;
1069 /* We ought to not compile any inline clones. */
1070 gcc_assert (!node->global.inlined_to);
1072 if (flag_unit_at_a_time)
1073 announce_function (decl);
1075 gcc_assert (node->lowered);
1077 if (DECL_IGNORED_P (decl))
1079 save_write_symbols = write_symbols;
1080 write_symbols = NO_DEBUG;
1081 save_debug_hooks = debug_hooks;
1082 debug_hooks = &do_nothing_debug_hooks;
1085 /* Generate RTL for the body of DECL. */
1086 lang_hooks.callgraph.expand_function (decl);
1088 /* Make sure that BE didn't give up on compiling. */
1089 /* ??? Can happen with nested function of extern inline. */
1090 gcc_assert (TREE_ASM_WRITTEN (node->decl));
1092 if (DECL_IGNORED_P (decl))
1094 write_symbols = save_write_symbols;
1095 debug_hooks = save_debug_hooks;
1098 current_function_decl = NULL;
1099 if (!cgraph_preserve_function_body_p (node->decl))
1101 cgraph_release_function_body (node);
1102 /* Eliminate all call edges. This is important so the call_expr no longer
1103 points to the dead function body. */
1104 cgraph_node_remove_callees (node);
1107 cgraph_function_flags_ready = true;
1110 /* Return true when CALLER_DECL should be inlined into CALLEE_DECL. */
1112 bool
1113 cgraph_inline_p (struct cgraph_edge *e, const char **reason)
1115 *reason = e->inline_failed;
1116 return !e->inline_failed;
1121 /* Expand all functions that must be output.
1123 Attempt to topologically sort the nodes so function is output when
1124 all called functions are already assembled to allow data to be
1125 propagated across the callgraph. Use a stack to get smaller distance
1126 between a function and its callees (later we may choose to use a more
1127 sophisticated algorithm for function reordering; we will likely want
1128 to use subsections to make the output functions appear in top-down
1129 order). */
1131 static void
1132 cgraph_expand_all_functions (void)
1134 struct cgraph_node *node;
1135 struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
1136 int order_pos = 0, new_order_pos = 0;
1137 int i;
1139 order_pos = cgraph_postorder (order);
1140 gcc_assert (order_pos == cgraph_n_nodes);
1142 /* Garbage collector may remove inline clones we eliminate during
1143 optimization. So we must be sure to not reference them. */
1144 for (i = 0; i < order_pos; i++)
1145 if (order[i]->output)
1146 order[new_order_pos++] = order[i];
1148 for (i = new_order_pos - 1; i >= 0; i--)
1150 node = order[i];
1151 if (node->output)
1153 gcc_assert (node->reachable);
1154 node->output = 0;
1155 cgraph_expand_function (node);
1158 cgraph_process_new_functions ();
1160 free (order);
1164 /* This is used to sort the node types by the cgraph order number. */
1166 struct cgraph_order_sort
1168 enum { ORDER_UNDEFINED = 0, ORDER_FUNCTION, ORDER_VAR, ORDER_ASM } kind;
1169 union
1171 struct cgraph_node *f;
1172 struct varpool_node *v;
1173 struct cgraph_asm_node *a;
1174 } u;
1177 /* Output all functions, variables, and asm statements in the order
1178 according to their order fields, which is the order in which they
1179 appeared in the file. This implements -fno-toplevel-reorder. In
1180 this mode we may output functions and variables which don't really
1181 need to be output. */
1183 static void
1184 cgraph_output_in_order (void)
1186 int max;
1187 size_t size;
1188 struct cgraph_order_sort *nodes;
1189 int i;
1190 struct cgraph_node *pf;
1191 struct varpool_node *pv;
1192 struct cgraph_asm_node *pa;
1194 max = cgraph_order;
1195 size = max * sizeof (struct cgraph_order_sort);
1196 nodes = (struct cgraph_order_sort *) alloca (size);
1197 memset (nodes, 0, size);
1199 varpool_analyze_pending_decls ();
1201 for (pf = cgraph_nodes; pf; pf = pf->next)
1203 if (pf->output)
1205 i = pf->order;
1206 gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
1207 nodes[i].kind = ORDER_FUNCTION;
1208 nodes[i].u.f = pf;
1212 for (pv = varpool_nodes_queue; pv; pv = pv->next_needed)
1214 i = pv->order;
1215 gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
1216 nodes[i].kind = ORDER_VAR;
1217 nodes[i].u.v = pv;
1220 for (pa = cgraph_asm_nodes; pa; pa = pa->next)
1222 i = pa->order;
1223 gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
1224 nodes[i].kind = ORDER_ASM;
1225 nodes[i].u.a = pa;
1228 for (i = 0; i < max; ++i)
1230 switch (nodes[i].kind)
1232 case ORDER_FUNCTION:
1233 nodes[i].u.f->output = 0;
1234 cgraph_expand_function (nodes[i].u.f);
1235 break;
1237 case ORDER_VAR:
1238 varpool_assemble_decl (nodes[i].u.v);
1239 break;
1241 case ORDER_ASM:
1242 assemble_asm (nodes[i].u.a->asm_str);
1243 break;
1245 case ORDER_UNDEFINED:
1246 break;
1248 default:
1249 gcc_unreachable ();
1253 cgraph_asm_nodes = NULL;
1256 /* Return true when function body of DECL still needs to be kept around
1257 for later re-use. */
1258 bool
1259 cgraph_preserve_function_body_p (tree decl)
1261 struct cgraph_node *node;
1262 if (!cgraph_global_info_ready)
1263 return (flag_really_no_inline
1264 ? lang_hooks.tree_inlining.disregard_inline_limits (decl)
1265 : DECL_INLINE (decl));
1266 /* Look if there is any clone around. */
1267 for (node = cgraph_node (decl); node; node = node->next_clone)
1268 if (node->global.inlined_to)
1269 return true;
1270 return false;
1273 static void
1274 ipa_passes (void)
1276 cfun = NULL;
1277 current_function_decl = NULL;
1278 tree_register_cfg_hooks ();
1279 bitmap_obstack_initialize (NULL);
1280 execute_ipa_pass_list (all_ipa_passes);
1281 bitmap_obstack_release (NULL);
1284 /* Perform simple optimizations based on callgraph. */
1286 void
1287 cgraph_optimize (void)
1289 if (errorcount || sorrycount)
1290 return;
1292 #ifdef ENABLE_CHECKING
1293 verify_cgraph ();
1294 #endif
1296 /* Call functions declared with the "constructor" or "destructor"
1297 attribute. */
1298 cgraph_build_cdtor_fns ();
1299 if (!flag_unit_at_a_time)
1301 cgraph_assemble_pending_functions ();
1302 cgraph_process_new_functions ();
1303 cgraph_state = CGRAPH_STATE_FINISHED;
1304 cgraph_output_pending_asms ();
1305 varpool_assemble_pending_decls ();
1306 varpool_output_debug_info ();
1307 return;
1310 /* Frontend may output common variables after the unit has been finalized.
1311 It is safe to deal with them here as they are always zero initialized. */
1312 varpool_analyze_pending_decls ();
1313 cgraph_analyze_functions ();
1315 timevar_push (TV_CGRAPHOPT);
1316 if (pre_ipa_mem_report)
1318 fprintf (stderr, "Memory consumption before IPA\n");
1319 dump_memory_report (false);
1321 if (!quiet_flag)
1322 fprintf (stderr, "Performing interprocedural optimizations\n");
1323 cgraph_state = CGRAPH_STATE_IPA;
1325 /* Don't run the IPA passes if there was any error or sorry messages. */
1326 if (errorcount == 0 && sorrycount == 0)
1327 ipa_passes ();
1329 /* This pass remove bodies of extern inline functions we never inlined.
1330 Do this later so other IPA passes see what is really going on. */
1331 cgraph_remove_unreachable_nodes (false, dump_file);
1332 cgraph_global_info_ready = true;
1333 if (cgraph_dump_file)
1335 fprintf (cgraph_dump_file, "Optimized ");
1336 dump_cgraph (cgraph_dump_file);
1337 dump_varpool (cgraph_dump_file);
1339 if (post_ipa_mem_report)
1341 fprintf (stderr, "Memory consumption after IPA\n");
1342 dump_memory_report (false);
1344 timevar_pop (TV_CGRAPHOPT);
1346 /* Output everything. */
1347 if (!quiet_flag)
1348 fprintf (stderr, "Assembling functions:\n");
1349 #ifdef ENABLE_CHECKING
1350 verify_cgraph ();
1351 #endif
1353 cgraph_mark_functions_to_output ();
1355 cgraph_state = CGRAPH_STATE_EXPANSION;
1356 if (!flag_toplevel_reorder)
1357 cgraph_output_in_order ();
1358 else
1360 cgraph_output_pending_asms ();
1362 cgraph_expand_all_functions ();
1363 varpool_remove_unreferenced_decls ();
1365 varpool_assemble_pending_decls ();
1366 varpool_output_debug_info ();
1368 cgraph_process_new_functions ();
1369 cgraph_state = CGRAPH_STATE_FINISHED;
1371 if (cgraph_dump_file)
1373 fprintf (cgraph_dump_file, "\nFinal ");
1374 dump_cgraph (cgraph_dump_file);
1376 #ifdef ENABLE_CHECKING
1377 verify_cgraph ();
1378 /* Double check that all inline clones are gone and that all
1379 function bodies have been released from memory. */
1380 if (flag_unit_at_a_time
1381 && !(sorrycount || errorcount))
1383 struct cgraph_node *node;
1384 bool error_found = false;
1386 for (node = cgraph_nodes; node; node = node->next)
1387 if (node->analyzed
1388 && (node->global.inlined_to
1389 || DECL_SAVED_TREE (node->decl)))
1391 error_found = true;
1392 dump_cgraph_node (stderr, node);
1394 if (error_found)
1395 internal_error ("nodes with no released memory found");
1397 #endif
1399 /* Generate and emit a static constructor or destructor. WHICH must be
1400 one of 'I' or 'D'. BODY should be a STATEMENT_LIST containing
1401 GENERIC statements. */
1403 void
1404 cgraph_build_static_cdtor (char which, tree body, int priority)
1406 static int counter = 0;
1407 char which_buf[16];
1408 tree decl, name, resdecl;
1410 sprintf (which_buf, "%c_%d", which, counter++);
1411 name = get_file_function_name (which_buf);
1413 decl = build_decl (FUNCTION_DECL, name,
1414 build_function_type (void_type_node, void_list_node));
1415 current_function_decl = decl;
1417 resdecl = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1418 DECL_ARTIFICIAL (resdecl) = 1;
1419 DECL_IGNORED_P (resdecl) = 1;
1420 DECL_RESULT (decl) = resdecl;
1422 allocate_struct_function (decl);
1424 TREE_STATIC (decl) = 1;
1425 TREE_USED (decl) = 1;
1426 DECL_ARTIFICIAL (decl) = 1;
1427 DECL_IGNORED_P (decl) = 1;
1428 DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
1429 DECL_SAVED_TREE (decl) = body;
1430 TREE_PUBLIC (decl) = ! targetm.have_ctors_dtors;
1431 DECL_UNINLINABLE (decl) = 1;
1433 DECL_INITIAL (decl) = make_node (BLOCK);
1434 TREE_USED (DECL_INITIAL (decl)) = 1;
1436 DECL_SOURCE_LOCATION (decl) = input_location;
1437 cfun->function_end_locus = input_location;
1439 switch (which)
1441 case 'I':
1442 DECL_STATIC_CONSTRUCTOR (decl) = 1;
1443 decl_init_priority_insert (decl, priority);
1444 break;
1445 case 'D':
1446 DECL_STATIC_DESTRUCTOR (decl) = 1;
1447 decl_fini_priority_insert (decl, priority);
1448 break;
1449 default:
1450 gcc_unreachable ();
1453 gimplify_function_tree (decl);
1455 cgraph_add_new_function (decl, false);
1456 cgraph_mark_needed_node (cgraph_node (decl));
1459 void
1460 init_cgraph (void)
1462 cgraph_dump_file = dump_begin (TDI_cgraph, NULL);
1465 /* The edges representing the callers of the NEW_VERSION node were
1466 fixed by cgraph_function_versioning (), now the call_expr in their
1467 respective tree code should be updated to call the NEW_VERSION. */
1469 static void
1470 update_call_expr (struct cgraph_node *new_version)
1472 struct cgraph_edge *e;
1474 gcc_assert (new_version);
1475 for (e = new_version->callers; e; e = e->next_caller)
1476 /* Update the call expr on the edges
1477 to call the new version. */
1478 TREE_OPERAND (CALL_EXPR_FN (get_call_expr_in (e->call_stmt)), 0) = new_version->decl;
1482 /* Create a new cgraph node which is the new version of
1483 OLD_VERSION node. REDIRECT_CALLERS holds the callers
1484 edges which should be redirected to point to
1485 NEW_VERSION. ALL the callees edges of OLD_VERSION
1486 are cloned to the new version node. Return the new
1487 version node. */
1489 static struct cgraph_node *
1490 cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
1491 tree new_decl,
1492 VEC(cgraph_edge_p,heap) *redirect_callers)
1494 struct cgraph_node *new_version;
1495 struct cgraph_edge *e, *new_e;
1496 struct cgraph_edge *next_callee;
1497 unsigned i;
1499 gcc_assert (old_version);
1501 new_version = cgraph_node (new_decl);
1503 new_version->analyzed = true;
1504 new_version->local = old_version->local;
1505 new_version->global = old_version->global;
1506 new_version->rtl = new_version->rtl;
1507 new_version->reachable = true;
1508 new_version->count = old_version->count;
1510 /* Clone the old node callees. Recursive calls are
1511 also cloned. */
1512 for (e = old_version->callees;e; e=e->next_callee)
1514 new_e = cgraph_clone_edge (e, new_version, e->call_stmt, 0, e->frequency,
1515 e->loop_nest, true);
1516 new_e->count = e->count;
1518 /* Fix recursive calls.
1519 If OLD_VERSION has a recursive call after the
1520 previous edge cloning, the new version will have an edge
1521 pointing to the old version, which is wrong;
1522 Redirect it to point to the new version. */
1523 for (e = new_version->callees ; e; e = next_callee)
1525 next_callee = e->next_callee;
1526 if (e->callee == old_version)
1527 cgraph_redirect_edge_callee (e, new_version);
1529 if (!next_callee)
1530 break;
1532 for (i = 0; VEC_iterate (cgraph_edge_p, redirect_callers, i, e); i++)
1534 /* Redirect calls to the old version node to point to its new
1535 version. */
1536 cgraph_redirect_edge_callee (e, new_version);
1539 return new_version;
1542 /* Perform function versioning.
1543 Function versioning includes copying of the tree and
1544 a callgraph update (creating a new cgraph node and updating
1545 its callees and callers).
1547 REDIRECT_CALLERS varray includes the edges to be redirected
1548 to the new version.
1550 TREE_MAP is a mapping of tree nodes we want to replace with
1551 new ones (according to results of prior analysis).
1552 OLD_VERSION_NODE is the node that is versioned.
1553 It returns the new version's cgraph node. */
1555 struct cgraph_node *
1556 cgraph_function_versioning (struct cgraph_node *old_version_node,
1557 VEC(cgraph_edge_p,heap) *redirect_callers,
1558 varray_type tree_map)
1560 tree old_decl = old_version_node->decl;
1561 struct cgraph_node *new_version_node = NULL;
1562 tree new_decl;
1564 if (!tree_versionable_function_p (old_decl))
1565 return NULL;
1567 /* Make a new FUNCTION_DECL tree node for the
1568 new version. */
1569 new_decl = copy_node (old_decl);
1571 /* Create the new version's call-graph node.
1572 and update the edges of the new node. */
1573 new_version_node =
1574 cgraph_copy_node_for_versioning (old_version_node, new_decl,
1575 redirect_callers);
1577 /* Copy the OLD_VERSION_NODE function tree to the new version. */
1578 tree_function_versioning (old_decl, new_decl, tree_map, false);
1579 /* Update the call_expr on the edges to call the new version node. */
1580 update_call_expr (new_version_node);
1582 /* Update the new version's properties.
1583 Make The new version visible only within this translation unit.
1584 ??? We cannot use COMDAT linkage because there is no
1585 ABI support for this. */
1586 DECL_EXTERNAL (new_version_node->decl) = 0;
1587 DECL_ONE_ONLY (new_version_node->decl) = 0;
1588 TREE_PUBLIC (new_version_node->decl) = 0;
1589 DECL_COMDAT (new_version_node->decl) = 0;
1590 new_version_node->local.externally_visible = 0;
1591 new_version_node->local.local = 1;
1592 new_version_node->lowered = true;
1593 return new_version_node;
1596 /* Produce separate function body for inline clones so the offline copy can be
1597 modified without affecting them. */
1598 struct cgraph_node *
1599 save_inline_function_body (struct cgraph_node *node)
1601 struct cgraph_node *first_clone;
1603 gcc_assert (node == cgraph_node (node->decl));
1605 cgraph_lower_function (node);
1607 /* In non-unit-at-a-time we construct full fledged clone we never output to
1608 assembly file. This clone is pointed out by inline_decl of original function
1609 and inlining infrastructure knows how to deal with this. */
1610 if (!flag_unit_at_a_time)
1612 struct cgraph_edge *e;
1614 first_clone = cgraph_clone_node (node, node->count, 0, CGRAPH_FREQ_BASE,
1615 false);
1616 first_clone->needed = 0;
1617 first_clone->reachable = 1;
1618 /* Recursively clone all bodies. */
1619 for (e = first_clone->callees; e; e = e->next_callee)
1620 if (!e->inline_failed)
1621 cgraph_clone_inlined_nodes (e, true, false);
1623 else
1624 first_clone = node->next_clone;
1626 first_clone->decl = copy_node (node->decl);
1627 node->next_clone = NULL;
1628 if (!flag_unit_at_a_time)
1629 node->inline_decl = first_clone->decl;
1630 first_clone->prev_clone = NULL;
1631 cgraph_insert_node_to_hashtable (first_clone);
1632 gcc_assert (first_clone == cgraph_node (first_clone->decl));
1634 /* Copy the OLD_VERSION_NODE function tree to the new version. */
1635 tree_function_versioning (node->decl, first_clone->decl, NULL, true);
1637 DECL_EXTERNAL (first_clone->decl) = 0;
1638 DECL_ONE_ONLY (first_clone->decl) = 0;
1639 TREE_PUBLIC (first_clone->decl) = 0;
1640 DECL_COMDAT (first_clone->decl) = 0;
1642 for (node = first_clone->next_clone; node; node = node->next_clone)
1643 node->decl = first_clone->decl;
1644 #ifdef ENABLE_CHECKING
1645 verify_cgraph_node (first_clone);
1646 #endif
1647 return first_clone;
1650 #include "gt-cgraphunit.h"