ChangeLog/libgcc
[official-gcc.git] / gcc / cgraphunit.c
blob1dba95bb06abb38c4ba5790e1a416fe22f64f63c
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 function
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 if (!flag_unit_at_a_time)
766 bitmap_obstack_initialize (NULL);
767 tree_register_cfg_hooks ();
768 execute_pass_list (pass_early_local_passes.sub);
769 free_dominance_info (CDI_POST_DOMINATORS);
770 free_dominance_info (CDI_DOMINATORS);
771 bitmap_obstack_release (NULL);
774 node->analyzed = true;
775 pop_cfun ();
776 current_function_decl = NULL;
779 /* Look for externally_visible and used attributes and mark cgraph nodes
780 accordingly.
782 We cannot mark the nodes at the point the attributes are processed (in
783 handle_*_attribute) because the copy of the declarations available at that
784 point may not be canonical. For example, in:
786 void f();
787 void f() __attribute__((used));
789 the declaration we see in handle_used_attribute will be the second
790 declaration -- but the front end will subsequently merge that declaration
791 with the original declaration and discard the second declaration.
793 Furthermore, we can't mark these nodes in cgraph_finalize_function because:
795 void f() {}
796 void f() __attribute__((externally_visible));
798 is valid.
800 So, we walk the nodes at the end of the translation unit, applying the
801 attributes at that point. */
803 static void
804 process_function_and_variable_attributes (struct cgraph_node *first,
805 struct varpool_node *first_var)
807 struct cgraph_node *node;
808 struct varpool_node *vnode;
810 for (node = cgraph_nodes; node != first; node = node->next)
812 tree decl = node->decl;
813 if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
815 mark_decl_referenced (decl);
816 if (node->local.finalized)
817 cgraph_mark_needed_node (node);
819 if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
821 if (! TREE_PUBLIC (node->decl))
822 warning (OPT_Wattributes,
823 "%J%<externally_visible%> attribute have effect only on public objects",
824 node->decl);
825 else
827 if (node->local.finalized)
828 cgraph_mark_needed_node (node);
829 node->local.externally_visible = true;
833 for (vnode = varpool_nodes; vnode != first_var; vnode = vnode->next)
835 tree decl = vnode->decl;
836 if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
838 mark_decl_referenced (decl);
839 if (vnode->finalized)
840 varpool_mark_needed_node (vnode);
842 if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
844 if (! TREE_PUBLIC (vnode->decl))
845 warning (OPT_Wattributes,
846 "%J%<externally_visible%> attribute have effect only on public objects",
847 vnode->decl);
848 else
850 if (vnode->finalized)
851 varpool_mark_needed_node (vnode);
852 vnode->externally_visible = true;
858 /* Process CGRAPH_NODES_NEEDED queue, analyze each function (and transitively
859 each reachable functions) and build cgraph.
860 The function can be called multiple times after inserting new nodes
861 into beginning of queue. Just the new part of queue is re-scanned then. */
863 static void
864 cgraph_analyze_functions (void)
866 /* Keep track of already processed nodes when called multiple times for
867 intermodule optimization. */
868 static struct cgraph_node *first_analyzed;
869 struct cgraph_node *first_processed = first_analyzed;
870 static struct varpool_node *first_analyzed_var;
871 struct cgraph_node *node, *next;
873 process_function_and_variable_attributes (first_processed,
874 first_analyzed_var);
875 first_processed = cgraph_nodes;
876 first_analyzed_var = varpool_nodes;
877 varpool_analyze_pending_decls ();
878 if (cgraph_dump_file)
880 fprintf (cgraph_dump_file, "Initial entry points:");
881 for (node = cgraph_nodes; node != first_analyzed; node = node->next)
882 if (node->needed && DECL_SAVED_TREE (node->decl))
883 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
884 fprintf (cgraph_dump_file, "\n");
886 cgraph_process_new_functions ();
888 /* Propagate reachability flag and lower representation of all reachable
889 functions. In the future, lowering will introduce new functions and
890 new entry points on the way (by template instantiation and virtual
891 method table generation for instance). */
892 while (cgraph_nodes_queue)
894 struct cgraph_edge *edge;
895 tree decl = cgraph_nodes_queue->decl;
897 node = cgraph_nodes_queue;
898 cgraph_nodes_queue = cgraph_nodes_queue->next_needed;
899 node->next_needed = NULL;
901 /* ??? It is possible to create extern inline function and later using
902 weak alias attribute to kill its body. See
903 gcc.c-torture/compile/20011119-1.c */
904 if (!DECL_SAVED_TREE (decl))
906 cgraph_reset_node (node);
907 continue;
910 gcc_assert (!node->analyzed && node->reachable);
911 gcc_assert (DECL_SAVED_TREE (decl));
913 cgraph_analyze_function (node);
915 for (edge = node->callees; edge; edge = edge->next_callee)
916 if (!edge->callee->reachable)
917 cgraph_mark_reachable_node (edge->callee);
919 /* We finalize local static variables during constructing callgraph
920 edges. Process their attributes too. */
921 process_function_and_variable_attributes (first_processed,
922 first_analyzed_var);
923 first_processed = cgraph_nodes;
924 first_analyzed_var = varpool_nodes;
925 varpool_analyze_pending_decls ();
926 cgraph_process_new_functions ();
929 /* Collect entry points to the unit. */
930 if (cgraph_dump_file)
932 fprintf (cgraph_dump_file, "Unit entry points:");
933 for (node = cgraph_nodes; node != first_analyzed; node = node->next)
934 if (node->needed && DECL_SAVED_TREE (node->decl))
935 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
936 fprintf (cgraph_dump_file, "\n\nInitial ");
937 dump_cgraph (cgraph_dump_file);
940 if (cgraph_dump_file)
941 fprintf (cgraph_dump_file, "\nReclaiming functions:");
943 for (node = cgraph_nodes; node != first_analyzed; node = next)
945 tree decl = node->decl;
946 next = node->next;
948 if (node->local.finalized && !DECL_SAVED_TREE (decl))
949 cgraph_reset_node (node);
951 if (!node->reachable && DECL_SAVED_TREE (decl))
953 if (cgraph_dump_file)
954 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
955 cgraph_remove_node (node);
956 continue;
958 else
959 node->next_needed = NULL;
960 gcc_assert (!node->local.finalized || DECL_SAVED_TREE (decl));
961 gcc_assert (node->analyzed == node->local.finalized);
963 if (cgraph_dump_file)
965 fprintf (cgraph_dump_file, "\n\nReclaimed ");
966 dump_cgraph (cgraph_dump_file);
968 first_analyzed = cgraph_nodes;
969 ggc_collect ();
972 /* Analyze the whole compilation unit once it is parsed completely. */
974 void
975 cgraph_finalize_compilation_unit (void)
977 if (errorcount || sorrycount)
978 return;
980 finish_aliases_1 ();
982 if (!flag_unit_at_a_time)
984 cgraph_output_pending_asms ();
985 cgraph_assemble_pending_functions ();
986 varpool_output_debug_info ();
987 return;
990 if (!quiet_flag)
992 fprintf (stderr, "\nAnalyzing compilation unit\n");
993 fflush (stderr);
996 timevar_push (TV_CGRAPH);
997 cgraph_analyze_functions ();
998 timevar_pop (TV_CGRAPH);
1000 /* Figure out what functions we want to assemble. */
1002 static void
1003 cgraph_mark_functions_to_output (void)
1005 struct cgraph_node *node;
1007 for (node = cgraph_nodes; node; node = node->next)
1009 tree decl = node->decl;
1010 struct cgraph_edge *e;
1012 gcc_assert (!node->output);
1014 for (e = node->callers; e; e = e->next_caller)
1015 if (e->inline_failed)
1016 break;
1018 /* We need to output all local functions that are used and not
1019 always inlined, as well as those that are reachable from
1020 outside the current compilation unit. */
1021 if (DECL_SAVED_TREE (decl)
1022 && !node->global.inlined_to
1023 && (node->needed
1024 || (e && node->reachable))
1025 && !TREE_ASM_WRITTEN (decl)
1026 && !DECL_EXTERNAL (decl))
1027 node->output = 1;
1028 else
1030 /* We should've reclaimed all functions that are not needed. */
1031 #ifdef ENABLE_CHECKING
1032 if (!node->global.inlined_to && DECL_SAVED_TREE (decl)
1033 && !DECL_EXTERNAL (decl))
1035 dump_cgraph_node (stderr, node);
1036 internal_error ("failed to reclaim unneeded function");
1038 #endif
1039 gcc_assert (node->global.inlined_to || !DECL_SAVED_TREE (decl)
1040 || DECL_EXTERNAL (decl));
1047 /* Expand function specified by NODE. */
1049 static void
1050 cgraph_expand_function (struct cgraph_node *node)
1052 enum debug_info_type save_write_symbols = NO_DEBUG;
1053 const struct gcc_debug_hooks *save_debug_hooks = NULL;
1054 tree decl = node->decl;
1056 /* We ought to not compile any inline clones. */
1057 gcc_assert (!node->global.inlined_to);
1059 if (flag_unit_at_a_time)
1060 announce_function (decl);
1062 gcc_assert (node->lowered);
1064 if (DECL_IGNORED_P (decl))
1066 save_write_symbols = write_symbols;
1067 write_symbols = NO_DEBUG;
1068 save_debug_hooks = debug_hooks;
1069 debug_hooks = &do_nothing_debug_hooks;
1072 /* Generate RTL for the body of DECL. */
1073 lang_hooks.callgraph.expand_function (decl);
1075 /* Make sure that BE didn't give up on compiling. */
1076 /* ??? Can happen with nested function of extern inline. */
1077 gcc_assert (TREE_ASM_WRITTEN (node->decl));
1079 if (DECL_IGNORED_P (decl))
1081 write_symbols = save_write_symbols;
1082 debug_hooks = save_debug_hooks;
1085 current_function_decl = NULL;
1086 if (!cgraph_preserve_function_body_p (node->decl))
1088 cgraph_release_function_body (node);
1089 /* Eliminate all call edges. This is important so the call_expr no longer
1090 points to the dead function body. */
1091 cgraph_node_remove_callees (node);
1094 cgraph_function_flags_ready = true;
1097 /* Return true when CALLER_DECL should be inlined into CALLEE_DECL. */
1099 bool
1100 cgraph_inline_p (struct cgraph_edge *e, const char **reason)
1102 *reason = e->inline_failed;
1103 return !e->inline_failed;
1108 /* Expand all functions that must be output.
1110 Attempt to topologically sort the nodes so function is output when
1111 all called functions are already assembled to allow data to be
1112 propagated across the callgraph. Use a stack to get smaller distance
1113 between a function and its callees (later we may choose to use a more
1114 sophisticated algorithm for function reordering; we will likely want
1115 to use subsections to make the output functions appear in top-down
1116 order). */
1118 static void
1119 cgraph_expand_all_functions (void)
1121 struct cgraph_node *node;
1122 struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
1123 int order_pos = 0, new_order_pos = 0;
1124 int i;
1126 order_pos = cgraph_postorder (order);
1127 gcc_assert (order_pos == cgraph_n_nodes);
1129 /* Garbage collector may remove inline clones we eliminate during
1130 optimization. So we must be sure to not reference them. */
1131 for (i = 0; i < order_pos; i++)
1132 if (order[i]->output)
1133 order[new_order_pos++] = order[i];
1135 for (i = new_order_pos - 1; i >= 0; i--)
1137 node = order[i];
1138 if (node->output)
1140 gcc_assert (node->reachable);
1141 node->output = 0;
1142 cgraph_expand_function (node);
1145 cgraph_process_new_functions ();
1147 free (order);
1151 /* This is used to sort the node types by the cgraph order number. */
1153 struct cgraph_order_sort
1155 enum { ORDER_UNDEFINED = 0, ORDER_FUNCTION, ORDER_VAR, ORDER_ASM } kind;
1156 union
1158 struct cgraph_node *f;
1159 struct varpool_node *v;
1160 struct cgraph_asm_node *a;
1161 } u;
1164 /* Output all functions, variables, and asm statements in the order
1165 according to their order fields, which is the order in which they
1166 appeared in the file. This implements -fno-toplevel-reorder. In
1167 this mode we may output functions and variables which don't really
1168 need to be output. */
1170 static void
1171 cgraph_output_in_order (void)
1173 int max;
1174 size_t size;
1175 struct cgraph_order_sort *nodes;
1176 int i;
1177 struct cgraph_node *pf;
1178 struct varpool_node *pv;
1179 struct cgraph_asm_node *pa;
1181 max = cgraph_order;
1182 size = max * sizeof (struct cgraph_order_sort);
1183 nodes = (struct cgraph_order_sort *) alloca (size);
1184 memset (nodes, 0, size);
1186 varpool_analyze_pending_decls ();
1188 for (pf = cgraph_nodes; pf; pf = pf->next)
1190 if (pf->output)
1192 i = pf->order;
1193 gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
1194 nodes[i].kind = ORDER_FUNCTION;
1195 nodes[i].u.f = pf;
1199 for (pv = varpool_nodes_queue; pv; pv = pv->next_needed)
1201 i = pv->order;
1202 gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
1203 nodes[i].kind = ORDER_VAR;
1204 nodes[i].u.v = pv;
1207 for (pa = cgraph_asm_nodes; pa; pa = pa->next)
1209 i = pa->order;
1210 gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
1211 nodes[i].kind = ORDER_ASM;
1212 nodes[i].u.a = pa;
1215 for (i = 0; i < max; ++i)
1217 switch (nodes[i].kind)
1219 case ORDER_FUNCTION:
1220 nodes[i].u.f->output = 0;
1221 cgraph_expand_function (nodes[i].u.f);
1222 break;
1224 case ORDER_VAR:
1225 varpool_assemble_decl (nodes[i].u.v);
1226 break;
1228 case ORDER_ASM:
1229 assemble_asm (nodes[i].u.a->asm_str);
1230 break;
1232 case ORDER_UNDEFINED:
1233 break;
1235 default:
1236 gcc_unreachable ();
1240 cgraph_asm_nodes = NULL;
1243 /* Return true when function body of DECL still needs to be kept around
1244 for later re-use. */
1245 bool
1246 cgraph_preserve_function_body_p (tree decl)
1248 struct cgraph_node *node;
1249 if (!cgraph_global_info_ready)
1250 return (flag_really_no_inline
1251 ? lang_hooks.tree_inlining.disregard_inline_limits (decl)
1252 : DECL_INLINE (decl));
1253 /* Look if there is any clone around. */
1254 for (node = cgraph_node (decl); node; node = node->next_clone)
1255 if (node->global.inlined_to)
1256 return true;
1257 return false;
1260 static void
1261 ipa_passes (void)
1263 cfun = NULL;
1264 current_function_decl = NULL;
1265 tree_register_cfg_hooks ();
1266 bitmap_obstack_initialize (NULL);
1267 execute_ipa_pass_list (all_ipa_passes);
1268 bitmap_obstack_release (NULL);
1271 /* Perform simple optimizations based on callgraph. */
1273 void
1274 cgraph_optimize (void)
1276 if (errorcount || sorrycount)
1277 return;
1279 #ifdef ENABLE_CHECKING
1280 verify_cgraph ();
1281 #endif
1283 /* Call functions declared with the "constructor" or "destructor"
1284 attribute. */
1285 cgraph_build_cdtor_fns ();
1286 if (!flag_unit_at_a_time)
1288 cgraph_assemble_pending_functions ();
1289 cgraph_process_new_functions ();
1290 cgraph_state = CGRAPH_STATE_FINISHED;
1291 cgraph_output_pending_asms ();
1292 varpool_assemble_pending_decls ();
1293 varpool_output_debug_info ();
1294 return;
1297 /* Frontend may output common variables after the unit has been finalized.
1298 It is safe to deal with them here as they are always zero initialized. */
1299 varpool_analyze_pending_decls ();
1300 cgraph_analyze_functions ();
1302 timevar_push (TV_CGRAPHOPT);
1303 if (pre_ipa_mem_report)
1305 fprintf (stderr, "Memory consumption before IPA\n");
1306 dump_memory_report (false);
1308 if (!quiet_flag)
1309 fprintf (stderr, "Performing interprocedural optimizations\n");
1310 cgraph_state = CGRAPH_STATE_IPA;
1312 /* Don't run the IPA passes if there was any error or sorry messages. */
1313 if (errorcount == 0 && sorrycount == 0)
1314 ipa_passes ();
1316 /* This pass remove bodies of extern inline functions we never inlined.
1317 Do this later so other IPA passes see what is really going on. */
1318 cgraph_remove_unreachable_nodes (false, dump_file);
1319 cgraph_global_info_ready = true;
1320 if (cgraph_dump_file)
1322 fprintf (cgraph_dump_file, "Optimized ");
1323 dump_cgraph (cgraph_dump_file);
1324 dump_varpool (cgraph_dump_file);
1326 if (post_ipa_mem_report)
1328 fprintf (stderr, "Memory consumption after IPA\n");
1329 dump_memory_report (false);
1331 timevar_pop (TV_CGRAPHOPT);
1333 /* Output everything. */
1334 if (!quiet_flag)
1335 fprintf (stderr, "Assembling functions:\n");
1336 #ifdef ENABLE_CHECKING
1337 verify_cgraph ();
1338 #endif
1340 cgraph_mark_functions_to_output ();
1342 cgraph_state = CGRAPH_STATE_EXPANSION;
1343 if (!flag_toplevel_reorder)
1344 cgraph_output_in_order ();
1345 else
1347 cgraph_output_pending_asms ();
1349 cgraph_expand_all_functions ();
1350 varpool_remove_unreferenced_decls ();
1352 varpool_assemble_pending_decls ();
1353 varpool_output_debug_info ();
1355 cgraph_process_new_functions ();
1356 cgraph_state = CGRAPH_STATE_FINISHED;
1358 if (cgraph_dump_file)
1360 fprintf (cgraph_dump_file, "\nFinal ");
1361 dump_cgraph (cgraph_dump_file);
1363 #ifdef ENABLE_CHECKING
1364 verify_cgraph ();
1365 /* Double check that all inline clones are gone and that all
1366 function bodies have been released from memory. */
1367 if (flag_unit_at_a_time
1368 && !(sorrycount || errorcount))
1370 struct cgraph_node *node;
1371 bool error_found = false;
1373 for (node = cgraph_nodes; node; node = node->next)
1374 if (node->analyzed
1375 && (node->global.inlined_to
1376 || DECL_SAVED_TREE (node->decl)))
1378 error_found = true;
1379 dump_cgraph_node (stderr, node);
1381 if (error_found)
1382 internal_error ("nodes with no released memory found");
1384 #endif
1386 /* Generate and emit a static constructor or destructor. WHICH must be
1387 one of 'I' or 'D'. BODY should be a STATEMENT_LIST containing
1388 GENERIC statements. */
1390 void
1391 cgraph_build_static_cdtor (char which, tree body, int priority)
1393 static int counter = 0;
1394 char which_buf[16];
1395 tree decl, name, resdecl;
1397 sprintf (which_buf, "%c_%d", which, counter++);
1398 name = get_file_function_name (which_buf);
1400 decl = build_decl (FUNCTION_DECL, name,
1401 build_function_type (void_type_node, void_list_node));
1402 current_function_decl = decl;
1404 resdecl = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1405 DECL_ARTIFICIAL (resdecl) = 1;
1406 DECL_IGNORED_P (resdecl) = 1;
1407 DECL_RESULT (decl) = resdecl;
1409 allocate_struct_function (decl);
1411 TREE_STATIC (decl) = 1;
1412 TREE_USED (decl) = 1;
1413 DECL_ARTIFICIAL (decl) = 1;
1414 DECL_IGNORED_P (decl) = 1;
1415 DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
1416 DECL_SAVED_TREE (decl) = body;
1417 TREE_PUBLIC (decl) = ! targetm.have_ctors_dtors;
1418 DECL_UNINLINABLE (decl) = 1;
1420 DECL_INITIAL (decl) = make_node (BLOCK);
1421 TREE_USED (DECL_INITIAL (decl)) = 1;
1423 DECL_SOURCE_LOCATION (decl) = input_location;
1424 cfun->function_end_locus = input_location;
1426 switch (which)
1428 case 'I':
1429 DECL_STATIC_CONSTRUCTOR (decl) = 1;
1430 decl_init_priority_insert (decl, priority);
1431 break;
1432 case 'D':
1433 DECL_STATIC_DESTRUCTOR (decl) = 1;
1434 decl_fini_priority_insert (decl, priority);
1435 break;
1436 default:
1437 gcc_unreachable ();
1440 gimplify_function_tree (decl);
1442 cgraph_add_new_function (decl, false);
1443 cgraph_mark_needed_node (cgraph_node (decl));
1446 void
1447 init_cgraph (void)
1449 cgraph_dump_file = dump_begin (TDI_cgraph, NULL);
1452 /* The edges representing the callers of the NEW_VERSION node were
1453 fixed by cgraph_function_versioning (), now the call_expr in their
1454 respective tree code should be updated to call the NEW_VERSION. */
1456 static void
1457 update_call_expr (struct cgraph_node *new_version)
1459 struct cgraph_edge *e;
1461 gcc_assert (new_version);
1462 for (e = new_version->callers; e; e = e->next_caller)
1463 /* Update the call expr on the edges
1464 to call the new version. */
1465 TREE_OPERAND (CALL_EXPR_FN (get_call_expr_in (e->call_stmt)), 0) = new_version->decl;
1469 /* Create a new cgraph node which is the new version of
1470 OLD_VERSION node. REDIRECT_CALLERS holds the callers
1471 edges which should be redirected to point to
1472 NEW_VERSION. ALL the callees edges of OLD_VERSION
1473 are cloned to the new version node. Return the new
1474 version node. */
1476 static struct cgraph_node *
1477 cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
1478 tree new_decl,
1479 VEC(cgraph_edge_p,heap) *redirect_callers)
1481 struct cgraph_node *new_version;
1482 struct cgraph_edge *e, *new_e;
1483 struct cgraph_edge *next_callee;
1484 unsigned i;
1486 gcc_assert (old_version);
1488 new_version = cgraph_node (new_decl);
1490 new_version->analyzed = true;
1491 new_version->local = old_version->local;
1492 new_version->global = old_version->global;
1493 new_version->rtl = new_version->rtl;
1494 new_version->reachable = true;
1495 new_version->count = old_version->count;
1497 /* Clone the old node callees. Recursive calls are
1498 also cloned. */
1499 for (e = old_version->callees;e; e=e->next_callee)
1501 new_e = cgraph_clone_edge (e, new_version, e->call_stmt, 0, e->frequency,
1502 e->loop_nest, true);
1503 new_e->count = e->count;
1505 /* Fix recursive calls.
1506 If OLD_VERSION has a recursive call after the
1507 previous edge cloning, the new version will have an edge
1508 pointing to the old version, which is wrong;
1509 Redirect it to point to the new version. */
1510 for (e = new_version->callees ; e; e = next_callee)
1512 next_callee = e->next_callee;
1513 if (e->callee == old_version)
1514 cgraph_redirect_edge_callee (e, new_version);
1516 if (!next_callee)
1517 break;
1519 for (i = 0; VEC_iterate (cgraph_edge_p, redirect_callers, i, e); i++)
1521 /* Redirect calls to the old version node to point to its new
1522 version. */
1523 cgraph_redirect_edge_callee (e, new_version);
1526 return new_version;
1529 /* Perform function versioning.
1530 Function versioning includes copying of the tree and
1531 a callgraph update (creating a new cgraph node and updating
1532 its callees and callers).
1534 REDIRECT_CALLERS varray includes the edges to be redirected
1535 to the new version.
1537 TREE_MAP is a mapping of tree nodes we want to replace with
1538 new ones (according to results of prior analysis).
1539 OLD_VERSION_NODE is the node that is versioned.
1540 It returns the new version's cgraph node. */
1542 struct cgraph_node *
1543 cgraph_function_versioning (struct cgraph_node *old_version_node,
1544 VEC(cgraph_edge_p,heap) *redirect_callers,
1545 varray_type tree_map)
1547 tree old_decl = old_version_node->decl;
1548 struct cgraph_node *new_version_node = NULL;
1549 tree new_decl;
1551 if (!tree_versionable_function_p (old_decl))
1552 return NULL;
1554 /* Make a new FUNCTION_DECL tree node for the
1555 new version. */
1556 new_decl = copy_node (old_decl);
1558 /* Create the new version's call-graph node.
1559 and update the edges of the new node. */
1560 new_version_node =
1561 cgraph_copy_node_for_versioning (old_version_node, new_decl,
1562 redirect_callers);
1564 /* Copy the OLD_VERSION_NODE function tree to the new version. */
1565 tree_function_versioning (old_decl, new_decl, tree_map, false);
1566 /* Update the call_expr on the edges to call the new version node. */
1567 update_call_expr (new_version_node);
1569 /* Update the new version's properties.
1570 Make The new version visible only within this translation unit.
1571 ??? We cannot use COMDAT linkage because there is no
1572 ABI support for this. */
1573 DECL_EXTERNAL (new_version_node->decl) = 0;
1574 DECL_ONE_ONLY (new_version_node->decl) = 0;
1575 TREE_PUBLIC (new_version_node->decl) = 0;
1576 DECL_COMDAT (new_version_node->decl) = 0;
1577 new_version_node->local.externally_visible = 0;
1578 new_version_node->local.local = 1;
1579 new_version_node->lowered = true;
1580 return new_version_node;
1583 /* Produce separate function body for inline clones so the offline copy can be
1584 modified without affecting them. */
1585 struct cgraph_node *
1586 save_inline_function_body (struct cgraph_node *node)
1588 struct cgraph_node *first_clone;
1590 gcc_assert (node == cgraph_node (node->decl));
1592 cgraph_lower_function (node);
1594 /* In non-unit-at-a-time we construct full fledged clone we never output to
1595 assembly file. This clone is pointed out by inline_decl of original function
1596 and inlining infrastructure knows how to deal with this. */
1597 if (!flag_unit_at_a_time)
1599 struct cgraph_edge *e;
1601 first_clone = cgraph_clone_node (node, node->count, 0, CGRAPH_FREQ_BASE,
1602 false);
1603 first_clone->needed = 0;
1604 first_clone->reachable = 1;
1605 /* Recursively clone all bodies. */
1606 for (e = first_clone->callees; e; e = e->next_callee)
1607 if (!e->inline_failed)
1608 cgraph_clone_inlined_nodes (e, true, false);
1610 else
1611 first_clone = node->next_clone;
1613 first_clone->decl = copy_node (node->decl);
1614 node->next_clone = NULL;
1615 if (!flag_unit_at_a_time)
1616 node->inline_decl = first_clone->decl;
1617 first_clone->prev_clone = NULL;
1618 cgraph_insert_node_to_hashtable (first_clone);
1619 gcc_assert (first_clone == cgraph_node (first_clone->decl));
1621 /* Copy the OLD_VERSION_NODE function tree to the new version. */
1622 tree_function_versioning (node->decl, first_clone->decl, NULL, true);
1624 DECL_EXTERNAL (first_clone->decl) = 0;
1625 DECL_ONE_ONLY (first_clone->decl) = 0;
1626 TREE_PUBLIC (first_clone->decl) = 0;
1627 DECL_COMDAT (first_clone->decl) = 0;
1629 for (node = first_clone->next_clone; node; node = node->next_clone)
1630 node->decl = first_clone->decl;
1631 #ifdef ENABLE_CHECKING
1632 verify_cgraph_node (first_clone);
1633 #endif
1634 return first_clone;
1637 #include "gt-cgraphunit.h"