1 /* Callgraph based interprocedural optimizations.
2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
3 2011, 2012 Free Software Foundation, Inc.
4 Contributed by Jan Hubicka
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
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
38 - varpool_finalize_variable
40 This function has same behavior as the above but is used for static
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 call-graph construction and local function analysis takes
49 place here. Bodies of unreachable functions are released to
50 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)
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 Analyzing of all functions is deferred
81 to cgraph_finalize_compilation_unit and expansion into cgraph_optimize.
83 In cgraph_finalize_compilation_unit the reachable functions are
84 analyzed. During analysis the call-graph edges from reachable
85 functions are constructed and their destinations are marked as
86 reachable. References to functions and variables are discovered too
87 and variables found to be needed output to the assembly file. Via
88 mark_referenced call in assemble_variable functions referenced by
89 static variables are noticed too.
91 The intra-procedural information is produced and its existence
92 indicated by global_info_ready. Once this flag is set it is impossible
93 to change function from !reachable to reachable and thus
94 assemble_variable no longer call mark_referenced.
96 Finally the call-graph is topologically sorted and all reachable functions
97 that has not been completely inlined or are not external are output.
99 ??? It is possible that reference to function or variable is optimized
100 out. We can not deal with this nicely because topological order is not
101 suitable for it. For tree-ssa we may consider another pass doing
102 optimization and re-discovering reachable functions.
104 ??? Reorganize code so variables are output very last and only if they
105 really has been referenced by produced code, so we catch more cases
106 where reference has been optimized out. */
111 #include "coretypes.h"
115 #include "tree-flow.h"
116 #include "tree-inline.h"
117 #include "langhooks.h"
118 #include "pointer-set.h"
125 #include "diagnostic.h"
126 #include "tree-pretty-print.h"
127 #include "gimple-pretty-print.h"
132 #include "function.h"
133 #include "ipa-prop.h"
135 #include "tree-iterator.h"
136 #include "tree-pass.h"
137 #include "tree-dump.h"
139 #include "coverage.h"
141 #include "ipa-inline.h"
142 #include "ipa-utils.h"
143 #include "lto-streamer.h"
145 static void cgraph_expand_all_functions (void);
146 static void cgraph_mark_functions_to_output (void);
147 static void cgraph_expand_function (struct cgraph_node *);
148 static void cgraph_output_pending_asms (void);
150 FILE *cgraph_dump_file;
152 /* Used for vtable lookup in thunk adjusting. */
153 static GTY (()) tree vtable_entry_type;
155 /* Determine if function DECL is needed. That is, visible to something
156 either outside this translation unit, something magic in the system
160 cgraph_decide_is_function_needed (struct cgraph_node *node, tree decl)
162 /* If the user told us it is used, then it must be so. */
163 if (node->local.externally_visible)
166 /* ??? If the assembler name is set by hand, it is possible to assemble
167 the name later after finalizing the function and the fact is noticed
168 in assemble_name then. This is arguably a bug. */
169 if (DECL_ASSEMBLER_NAME_SET_P (decl)
170 && (!node->thunk.thunk_p && !node->same_body_alias)
171 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
174 /* With -fkeep-inline-functions we are keeping all inline functions except
175 for extern inline ones. */
176 if (flag_keep_inline_functions
177 && DECL_DECLARED_INLINE_P (decl)
178 && !DECL_EXTERNAL (decl)
179 && !DECL_DISREGARD_INLINE_LIMITS (decl))
182 /* If we decided it was needed before, but at the time we didn't have
183 the body of the function available, then it's still needed. We have
184 to go back and re-check its dependencies now. */
188 /* Externally visible functions must be output. The exception is
189 COMDAT functions that must be output only when they are needed.
191 When not optimizing, also output the static functions. (see
192 PR24561), but don't do so for always_inline functions, functions
193 declared inline and nested functions. These were optimized out
194 in the original implementation and it is unclear whether we want
195 to change the behavior here. */
196 if (((TREE_PUBLIC (decl)
198 && !node->same_body_alias
199 && !DECL_DISREGARD_INLINE_LIMITS (decl)
200 && !DECL_DECLARED_INLINE_P (decl)
201 && !(DECL_CONTEXT (decl)
202 && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)))
203 && !flag_whole_program
205 && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
211 /* Process CGRAPH_NEW_FUNCTIONS and perform actions necessary to add these
212 functions into callgraph in a way so they look like ordinary reachable
213 functions inserted into callgraph already at construction time. */
216 cgraph_process_new_functions (void)
220 struct cgraph_node *node;
222 varpool_analyze_pending_decls ();
223 /* Note that this queue may grow as its being processed, as the new
224 functions may generate new ones. */
225 while (cgraph_new_nodes)
227 node = cgraph_new_nodes;
229 cgraph_new_nodes = cgraph_new_nodes->next_needed;
230 switch (cgraph_state)
232 case CGRAPH_STATE_CONSTRUCTION:
233 /* At construction time we just need to finalize function and move
234 it into reachable functions list. */
236 node->next_needed = NULL;
237 cgraph_finalize_function (fndecl, false);
238 cgraph_mark_reachable_node (node);
240 cgraph_call_function_insertion_hooks (node);
243 case CGRAPH_STATE_IPA:
244 case CGRAPH_STATE_IPA_SSA:
245 /* When IPA optimization already started, do all essential
246 transformations that has been already performed on the whole
247 cgraph but not on this function. */
249 gimple_register_cfg_hooks ();
251 cgraph_analyze_function (node);
252 push_cfun (DECL_STRUCT_FUNCTION (fndecl));
253 current_function_decl = fndecl;
254 if ((cgraph_state == CGRAPH_STATE_IPA_SSA
255 && !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
256 /* When not optimizing, be sure we run early local passes anyway
259 execute_pass_list (pass_early_local_passes.pass.sub);
261 compute_inline_parameters (node, true);
262 free_dominance_info (CDI_POST_DOMINATORS);
263 free_dominance_info (CDI_DOMINATORS);
265 current_function_decl = NULL;
266 cgraph_call_function_insertion_hooks (node);
269 case CGRAPH_STATE_EXPANSION:
270 /* Functions created during expansion shall be compiled
273 cgraph_call_function_insertion_hooks (node);
274 cgraph_expand_function (node);
281 varpool_analyze_pending_decls ();
286 /* As an GCC extension we allow redefinition of the function. The
287 semantics when both copies of bodies differ is not well defined.
288 We replace the old body with new body so in unit at a time mode
289 we always use new body, while in normal mode we may end up with
290 old body inlined into some functions and new body expanded and
293 ??? It may make more sense to use one body for inlining and other
294 body for expanding the function but this is difficult to do. */
297 cgraph_reset_node (struct cgraph_node *node)
299 /* If node->process is set, then we have already begun whole-unit analysis.
300 This is *not* testing for whether we've already emitted the function.
301 That case can be sort-of legitimately seen with real function redefinition
302 errors. I would argue that the front end should never present us with
303 such a case, but don't enforce that for now. */
304 gcc_assert (!node->process);
306 /* Reset our data structures so we can analyze the function again. */
307 memset (&node->local, 0, sizeof (node->local));
308 memset (&node->global, 0, sizeof (node->global));
309 memset (&node->rtl, 0, sizeof (node->rtl));
310 node->analyzed = false;
311 node->local.finalized = false;
313 cgraph_node_remove_callees (node);
317 cgraph_lower_function (struct cgraph_node *node)
323 lower_nested_functions (node->decl);
324 gcc_assert (!node->nested);
326 tree_lowering_passes (node->decl);
327 node->lowered = true;
330 /* DECL has been parsed. Take it, queue it, compile it at the whim of the
331 logic in effect. If NESTED is true, then our caller cannot stand to have
332 the garbage collector run at the moment. We would need to either create
333 a new GC context, or just not compile right now. */
336 cgraph_finalize_function (tree decl, bool nested)
338 struct cgraph_node *node = cgraph_get_create_node (decl);
340 if (node->local.finalized)
342 cgraph_reset_node (node);
343 node->local.redefined_extern_inline = true;
346 notice_global_symbol (decl);
347 node->local.finalized = true;
348 node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL;
350 if (cgraph_decide_is_function_needed (node, decl))
351 cgraph_mark_needed_node (node);
353 /* Since we reclaim unreachable nodes at the end of every language
354 level unit, we need to be conservative about possible entry points
356 if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
357 || DECL_STATIC_CONSTRUCTOR (decl)
358 || DECL_STATIC_DESTRUCTOR (decl)
359 /* COMDAT virtual functions may be referenced by vtable from
360 other compilation unit. Still we want to devirtualize calls
361 to those so we need to analyze them.
362 FIXME: We should introduce may edges for this purpose and update
363 their handling in unreachable function removal and inliner too. */
364 || (DECL_VIRTUAL_P (decl)
365 && optimize && (DECL_COMDAT (decl) || DECL_EXTERNAL (decl))))
366 cgraph_mark_reachable_node (node);
368 /* If we've not yet emitted decl, tell the debug info about it. */
369 if (!TREE_ASM_WRITTEN (decl))
370 (*debug_hooks->deferred_inline_function) (decl);
372 /* Possibly warn about unused parameters. */
373 if (warn_unused_parameter)
374 do_warn_unused_parameter (decl);
380 /* C99 extern inline keywords allow changing of declaration after function
381 has been finalized. We need to re-decide if we want to mark the function as
385 cgraph_mark_if_needed (tree decl)
387 struct cgraph_node *node = cgraph_get_node (decl);
388 if (node->local.finalized && cgraph_decide_is_function_needed (node, decl))
389 cgraph_mark_needed_node (node);
392 /* Return TRUE if NODE2 is equivalent to NODE or its clone. */
394 clone_of_p (struct cgraph_node *node, struct cgraph_node *node2)
396 node = cgraph_function_or_thunk_node (node, NULL);
397 node2 = cgraph_function_or_thunk_node (node2, NULL);
398 while (node != node2 && node2)
399 node2 = node2->clone_of;
400 return node2 != NULL;
403 /* Verify edge E count and frequency. */
406 verify_edge_count_and_frequency (struct cgraph_edge *e)
408 bool error_found = false;
411 error ("caller edge count is negative");
414 if (e->frequency < 0)
416 error ("caller edge frequency is negative");
419 if (e->frequency > CGRAPH_FREQ_MAX)
421 error ("caller edge frequency is too large");
424 if (gimple_has_body_p (e->caller->decl)
425 && !e->caller->global.inlined_to
426 /* FIXME: Inline-analysis sets frequency to 0 when edge is optimized out.
427 Remove this once edges are actualy removed from the function at that time. */
429 || (inline_edge_summary_vec
430 && ((VEC_length(inline_edge_summary_t, inline_edge_summary_vec)
431 <= (unsigned) e->uid)
432 || !inline_edge_summary (e)->predicate)))
434 != compute_call_stmt_bb_frequency (e->caller->decl,
435 gimple_bb (e->call_stmt))))
437 error ("caller edge frequency %i does not match BB frequency %i",
439 compute_call_stmt_bb_frequency (e->caller->decl,
440 gimple_bb (e->call_stmt)));
446 /* Switch to THIS_CFUN if needed and print STMT to stderr. */
448 cgraph_debug_gimple_stmt (struct function *this_cfun, gimple stmt)
450 /* debug_gimple_stmt needs correct cfun */
451 if (cfun != this_cfun)
452 set_cfun (this_cfun);
453 debug_gimple_stmt (stmt);
456 /* Verify that call graph edge E corresponds to DECL from the associated
457 statement. Return true if the verification should fail. */
460 verify_edge_corresponds_to_fndecl (struct cgraph_edge *e, tree decl)
462 struct cgraph_node *node;
464 if (!decl || e->callee->global.inlined_to)
466 node = cgraph_get_node (decl);
468 /* We do not know if a node from a different partition is an alias or what it
469 aliases and therefore cannot do the former_clone_of check reliably. */
470 if (!node || node->in_other_partition)
472 node = cgraph_function_or_thunk_node (node, NULL);
474 if ((e->callee->former_clone_of != node->decl)
475 /* IPA-CP sometimes redirect edge to clone and then back to the former
476 function. This ping-pong has to go, eventaully. */
477 && (node != cgraph_function_or_thunk_node (e->callee, NULL))
478 && !clone_of_p (node, e->callee))
484 /* Verify cgraph nodes of given cgraph node. */
486 verify_cgraph_node (struct cgraph_node *node)
488 struct cgraph_edge *e;
489 struct function *this_cfun = DECL_STRUCT_FUNCTION (node->decl);
490 basic_block this_block;
491 gimple_stmt_iterator gsi;
492 bool error_found = false;
497 timevar_push (TV_CGRAPH_VERIFY);
498 for (e = node->callees; e; e = e->next_callee)
501 error ("aux field set for edge %s->%s",
502 identifier_to_locale (cgraph_node_name (e->caller)),
503 identifier_to_locale (cgraph_node_name (e->callee)));
508 error ("execution count is negative");
511 if (node->global.inlined_to && node->local.externally_visible)
513 error ("externally visible inline clone");
516 if (node->global.inlined_to && node->address_taken)
518 error ("inline clone with address taken");
521 if (node->global.inlined_to && node->needed)
523 error ("inline clone is needed");
526 for (e = node->indirect_calls; e; e = e->next_callee)
530 error ("aux field set for indirect edge from %s",
531 identifier_to_locale (cgraph_node_name (e->caller)));
534 if (!e->indirect_unknown_callee
535 || !e->indirect_info)
537 error ("An indirect edge from %s is not marked as indirect or has "
538 "associated indirect_info, the corresponding statement is: ",
539 identifier_to_locale (cgraph_node_name (e->caller)));
540 cgraph_debug_gimple_stmt (this_cfun, e->call_stmt);
544 for (e = node->callers; e; e = e->next_caller)
546 if (verify_edge_count_and_frequency (e))
548 if (!e->inline_failed)
550 if (node->global.inlined_to
551 != (e->caller->global.inlined_to
552 ? e->caller->global.inlined_to : e->caller))
554 error ("inlined_to pointer is wrong");
557 if (node->callers->next_caller)
559 error ("multiple inline callers");
564 if (node->global.inlined_to)
566 error ("inlined_to pointer set for noninline callers");
570 for (e = node->indirect_calls; e; e = e->next_callee)
571 if (verify_edge_count_and_frequency (e))
573 if (!node->callers && node->global.inlined_to)
575 error ("inlined_to pointer is set but no predecessors found");
578 if (node->global.inlined_to == node)
580 error ("inlined_to pointer refers to itself");
584 if (!cgraph_get_node (node->decl))
586 error ("node not found in cgraph_hash");
592 struct cgraph_node *n;
593 for (n = node->clone_of->clones; n; n = n->next_sibling_clone)
598 error ("node has wrong clone_of");
604 struct cgraph_node *n;
605 for (n = node->clones; n; n = n->next_sibling_clone)
606 if (n->clone_of != node)
610 error ("node has wrong clone list");
614 if ((node->prev_sibling_clone || node->next_sibling_clone) && !node->clone_of)
616 error ("node is in clone list but it is not clone");
619 if (!node->prev_sibling_clone && node->clone_of && node->clone_of->clones != node)
621 error ("node has wrong prev_clone pointer");
624 if (node->prev_sibling_clone && node->prev_sibling_clone->next_sibling_clone != node)
626 error ("double linked list of clones corrupted");
629 if (node->same_comdat_group)
631 struct cgraph_node *n = node->same_comdat_group;
633 if (!DECL_ONE_ONLY (node->decl))
635 error ("non-DECL_ONE_ONLY node in a same_comdat_group list");
640 error ("node is alone in a comdat group");
645 if (!n->same_comdat_group)
647 error ("same_comdat_group is not a circular list");
651 n = n->same_comdat_group;
656 if (node->analyzed && node->alias)
658 bool ref_found = false;
664 error ("Alias has call edges");
667 for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
668 if (ref->use != IPA_REF_ALIAS)
670 error ("Alias has non-alias refernece");
675 error ("Alias has more than one alias reference");
682 error ("Analyzed alias has no reference");
686 if (node->analyzed && node->thunk.thunk_p)
690 error ("No edge out of thunk node");
693 else if (node->callees->next_callee)
695 error ("More than one edge out of thunk node");
698 if (gimple_has_body_p (node->decl))
700 error ("Thunk is not supposed to have body");
704 else if (node->analyzed && gimple_has_body_p (node->decl)
705 && !TREE_ASM_WRITTEN (node->decl)
706 && (!DECL_EXTERNAL (node->decl) || node->global.inlined_to)
711 /* The nodes we're interested in are never shared, so walk
712 the tree ignoring duplicates. */
713 struct pointer_set_t *visited_nodes = pointer_set_create ();
714 /* Reach the trees by walking over the CFG, and note the
715 enclosing basic-blocks in the call edges. */
716 FOR_EACH_BB_FN (this_block, this_cfun)
717 for (gsi = gsi_start_bb (this_block);
721 gimple stmt = gsi_stmt (gsi);
722 if (is_gimple_call (stmt))
724 struct cgraph_edge *e = cgraph_edge (node, stmt);
725 tree decl = gimple_call_fndecl (stmt);
730 error ("shared call_stmt:");
731 cgraph_debug_gimple_stmt (this_cfun, stmt);
734 if (!e->indirect_unknown_callee)
736 if (verify_edge_corresponds_to_fndecl (e, decl))
738 error ("edge points to wrong declaration:");
739 debug_tree (e->callee->decl);
740 fprintf (stderr," Instead of:");
747 error ("an indirect edge with unknown callee "
748 "corresponding to a call_stmt with "
749 "a known declaration:");
751 cgraph_debug_gimple_stmt (this_cfun, e->call_stmt);
757 error ("missing callgraph edge for call stmt:");
758 cgraph_debug_gimple_stmt (this_cfun, stmt);
763 pointer_set_destroy (visited_nodes);
766 /* No CFG available?! */
769 for (e = node->callees; e; e = e->next_callee)
773 error ("edge %s->%s has no corresponding call_stmt",
774 identifier_to_locale (cgraph_node_name (e->caller)),
775 identifier_to_locale (cgraph_node_name (e->callee)));
776 cgraph_debug_gimple_stmt (this_cfun, e->call_stmt);
781 for (e = node->indirect_calls; e; e = e->next_callee)
785 error ("an indirect edge from %s has no corresponding call_stmt",
786 identifier_to_locale (cgraph_node_name (e->caller)));
787 cgraph_debug_gimple_stmt (this_cfun, e->call_stmt);
795 dump_cgraph_node (stderr, node);
796 internal_error ("verify_cgraph_node failed");
798 timevar_pop (TV_CGRAPH_VERIFY);
801 /* Verify whole cgraph structure. */
805 struct cgraph_node *node;
810 for (node = cgraph_nodes; node; node = node->next)
811 verify_cgraph_node (node);
814 /* Output all asm statements we have stored up to be output. */
817 cgraph_output_pending_asms (void)
819 struct cgraph_asm_node *can;
824 for (can = cgraph_asm_nodes; can; can = can->next)
825 assemble_asm (can->asm_str);
826 cgraph_asm_nodes = NULL;
829 /* Analyze the function scheduled to be output. */
831 cgraph_analyze_function (struct cgraph_node *node)
833 tree save = current_function_decl;
834 tree decl = node->decl;
836 if (node->alias && node->thunk.alias)
838 struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
839 if (!VEC_length (ipa_ref_t, node->ref_list.references))
840 ipa_record_reference (node, NULL, tgt, NULL, IPA_REF_ALIAS, NULL);
841 if (node->same_body_alias)
843 DECL_VIRTUAL_P (node->decl) = DECL_VIRTUAL_P (node->thunk.alias);
844 DECL_DECLARED_INLINE_P (node->decl)
845 = DECL_DECLARED_INLINE_P (node->thunk.alias);
846 DECL_DISREGARD_INLINE_LIMITS (node->decl)
847 = DECL_DISREGARD_INLINE_LIMITS (node->thunk.alias);
850 /* Fixup visibility nonsences C++ frontend produce on same body aliases. */
851 if (TREE_PUBLIC (node->decl) && node->same_body_alias)
853 DECL_EXTERNAL (node->decl) = DECL_EXTERNAL (node->thunk.alias);
854 if (DECL_ONE_ONLY (node->thunk.alias))
856 DECL_COMDAT (node->decl) = DECL_COMDAT (node->thunk.alias);
857 DECL_COMDAT_GROUP (node->decl) = DECL_COMDAT_GROUP (node->thunk.alias);
858 if (DECL_ONE_ONLY (node->thunk.alias) && !node->same_comdat_group)
860 struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
861 node->same_comdat_group = tgt;
862 if (!tgt->same_comdat_group)
863 tgt->same_comdat_group = node;
866 struct cgraph_node *n;
867 for (n = tgt->same_comdat_group;
868 n->same_comdat_group != tgt;
869 n = n->same_comdat_group)
871 n->same_comdat_group = node;
876 cgraph_mark_reachable_node (cgraph_alias_aliased_node (node));
877 if (node->address_taken)
878 cgraph_mark_address_taken_node (cgraph_alias_aliased_node (node));
879 if (cgraph_decide_is_function_needed (node, node->decl))
880 cgraph_mark_needed_node (node);
882 else if (node->thunk.thunk_p)
884 cgraph_create_edge (node, cgraph_get_node (node->thunk.alias),
885 NULL, 0, CGRAPH_FREQ_BASE);
889 current_function_decl = decl;
890 push_cfun (DECL_STRUCT_FUNCTION (decl));
892 assign_assembler_name_if_neeeded (node->decl);
894 /* Make sure to gimplify bodies only once. During analyzing a
895 function we lower it, which will require gimplified nested
896 functions, so we can end up here with an already gimplified
898 if (!gimple_body (decl))
899 gimplify_function_tree (decl);
900 dump_function (TDI_generic, decl);
902 cgraph_lower_function (node);
905 node->analyzed = true;
907 current_function_decl = save;
910 /* C++ frontend produce same body aliases all over the place, even before PCH
911 gets streamed out. It relies on us linking the aliases with their function
912 in order to do the fixups, but ipa-ref is not PCH safe. Consequentely we
913 first produce aliases without links, but once C++ FE is sure he won't sream
914 PCH we build the links via this function. */
917 cgraph_process_same_body_aliases (void)
919 struct cgraph_node *node;
920 for (node = cgraph_nodes; node; node = node->next)
921 if (node->same_body_alias
922 && !VEC_length (ipa_ref_t, node->ref_list.references))
924 struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
925 ipa_record_reference (node, NULL, tgt, NULL, IPA_REF_ALIAS, NULL);
927 same_body_aliases_done = true;
930 /* Process attributes common for vars and functions. */
933 process_common_attributes (tree decl)
935 tree weakref = lookup_attribute ("weakref", DECL_ATTRIBUTES (decl));
937 if (weakref && !lookup_attribute ("alias", DECL_ATTRIBUTES (decl)))
939 warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
940 "%<weakref%> attribute should be accompanied with"
941 " an %<alias%> attribute");
942 DECL_WEAK (decl) = 0;
943 DECL_ATTRIBUTES (decl) = remove_attribute ("weakref",
944 DECL_ATTRIBUTES (decl));
948 /* Look for externally_visible and used attributes and mark cgraph nodes
951 We cannot mark the nodes at the point the attributes are processed (in
952 handle_*_attribute) because the copy of the declarations available at that
953 point may not be canonical. For example, in:
956 void f() __attribute__((used));
958 the declaration we see in handle_used_attribute will be the second
959 declaration -- but the front end will subsequently merge that declaration
960 with the original declaration and discard the second declaration.
962 Furthermore, we can't mark these nodes in cgraph_finalize_function because:
965 void f() __attribute__((externally_visible));
969 So, we walk the nodes at the end of the translation unit, applying the
970 attributes at that point. */
973 process_function_and_variable_attributes (struct cgraph_node *first,
974 struct varpool_node *first_var)
976 struct cgraph_node *node;
977 struct varpool_node *vnode;
979 for (node = cgraph_nodes; node != first; node = node->next)
981 tree decl = node->decl;
982 if (DECL_PRESERVE_P (decl))
983 cgraph_mark_needed_node (node);
984 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
985 && lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))
986 && TREE_PUBLIC (node->decl))
988 if (node->local.finalized)
989 cgraph_mark_needed_node (node);
991 else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
993 if (! TREE_PUBLIC (node->decl))
994 warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wattributes,
995 "%<externally_visible%>"
996 " attribute have effect only on public objects");
997 else if (node->local.finalized)
998 cgraph_mark_needed_node (node);
1000 if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
1001 && (node->local.finalized && !node->alias))
1003 warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wattributes,
1004 "%<weakref%> attribute ignored"
1005 " because function is defined");
1006 DECL_WEAK (decl) = 0;
1007 DECL_ATTRIBUTES (decl) = remove_attribute ("weakref",
1008 DECL_ATTRIBUTES (decl));
1011 if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (decl))
1012 && !DECL_DECLARED_INLINE_P (decl)
1013 /* redefining extern inline function makes it DECL_UNINLINABLE. */
1014 && !DECL_UNINLINABLE (decl))
1015 warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
1016 "always_inline function might not be inlinable");
1018 process_common_attributes (decl);
1020 for (vnode = varpool_nodes; vnode != first_var; vnode = vnode->next)
1022 tree decl = vnode->decl;
1023 if (DECL_PRESERVE_P (decl))
1025 vnode->force_output = true;
1026 if (vnode->finalized)
1027 varpool_mark_needed_node (vnode);
1029 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
1030 && lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))
1031 && TREE_PUBLIC (vnode->decl))
1033 if (vnode->finalized)
1034 varpool_mark_needed_node (vnode);
1036 else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
1038 if (! TREE_PUBLIC (vnode->decl))
1039 warning_at (DECL_SOURCE_LOCATION (vnode->decl), OPT_Wattributes,
1040 "%<externally_visible%>"
1041 " attribute have effect only on public objects");
1042 else if (vnode->finalized)
1043 varpool_mark_needed_node (vnode);
1045 if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
1047 && DECL_INITIAL (decl))
1049 warning_at (DECL_SOURCE_LOCATION (vnode->decl), OPT_Wattributes,
1050 "%<weakref%> attribute ignored"
1051 " because variable is initialized");
1052 DECL_WEAK (decl) = 0;
1053 DECL_ATTRIBUTES (decl) = remove_attribute ("weakref",
1054 DECL_ATTRIBUTES (decl));
1056 process_common_attributes (decl);
1060 /* Process CGRAPH_NODES_NEEDED queue, analyze each function (and transitively
1061 each reachable functions) and build cgraph.
1062 The function can be called multiple times after inserting new nodes
1063 into beginning of queue. Just the new part of queue is re-scanned then. */
1066 cgraph_analyze_functions (void)
1068 /* Keep track of already processed nodes when called multiple times for
1069 intermodule optimization. */
1070 static struct cgraph_node *first_analyzed;
1071 struct cgraph_node *first_processed = first_analyzed;
1072 static struct varpool_node *first_analyzed_var;
1073 struct cgraph_node *node, *next;
1075 bitmap_obstack_initialize (NULL);
1076 process_function_and_variable_attributes (first_processed,
1077 first_analyzed_var);
1078 first_processed = cgraph_nodes;
1079 first_analyzed_var = varpool_nodes;
1080 varpool_analyze_pending_decls ();
1081 if (cgraph_dump_file)
1083 fprintf (cgraph_dump_file, "Initial entry points:");
1084 for (node = cgraph_nodes; node != first_analyzed; node = node->next)
1086 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
1087 fprintf (cgraph_dump_file, "\n");
1089 cgraph_process_new_functions ();
1091 /* Propagate reachability flag and lower representation of all reachable
1092 functions. In the future, lowering will introduce new functions and
1093 new entry points on the way (by template instantiation and virtual
1094 method table generation for instance). */
1095 while (cgraph_nodes_queue)
1097 struct cgraph_edge *edge;
1098 tree decl = cgraph_nodes_queue->decl;
1100 node = cgraph_nodes_queue;
1101 cgraph_nodes_queue = cgraph_nodes_queue->next_needed;
1102 node->next_needed = NULL;
1104 /* ??? It is possible to create extern inline function and later using
1105 weak alias attribute to kill its body. See
1106 gcc.c-torture/compile/20011119-1.c */
1107 if (!DECL_STRUCT_FUNCTION (decl)
1108 && (!node->alias || !node->thunk.alias)
1109 && !node->thunk.thunk_p)
1111 cgraph_reset_node (node);
1112 node->local.redefined_extern_inline = true;
1116 if (!node->analyzed)
1117 cgraph_analyze_function (node);
1119 for (edge = node->callees; edge; edge = edge->next_callee)
1120 if (!edge->callee->reachable)
1121 cgraph_mark_reachable_node (edge->callee);
1122 for (edge = node->callers; edge; edge = edge->next_caller)
1123 if (!edge->caller->reachable && edge->caller->thunk.thunk_p)
1124 cgraph_mark_reachable_node (edge->caller);
1126 if (node->same_comdat_group)
1128 for (next = node->same_comdat_group;
1130 next = next->same_comdat_group)
1131 cgraph_mark_reachable_node (next);
1134 /* If decl is a clone of an abstract function, mark that abstract
1135 function so that we don't release its body. The DECL_INITIAL() of that
1136 abstract function declaration will be later needed to output debug
1138 if (DECL_ABSTRACT_ORIGIN (decl))
1140 struct cgraph_node *origin_node;
1141 origin_node = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
1142 origin_node->abstract_and_needed = true;
1145 /* We finalize local static variables during constructing callgraph
1146 edges. Process their attributes too. */
1147 process_function_and_variable_attributes (first_processed,
1148 first_analyzed_var);
1149 first_processed = cgraph_nodes;
1150 first_analyzed_var = varpool_nodes;
1151 varpool_analyze_pending_decls ();
1152 cgraph_process_new_functions ();
1155 /* Collect entry points to the unit. */
1156 if (cgraph_dump_file)
1158 fprintf (cgraph_dump_file, "Unit entry points:");
1159 for (node = cgraph_nodes; node != first_analyzed; node = node->next)
1161 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
1162 fprintf (cgraph_dump_file, "\n\nInitial ");
1163 dump_cgraph (cgraph_dump_file);
1164 dump_varpool (cgraph_dump_file);
1167 if (cgraph_dump_file)
1168 fprintf (cgraph_dump_file, "\nReclaiming functions:");
1170 for (node = cgraph_nodes; node != first_analyzed; node = next)
1172 tree decl = node->decl;
1175 if (node->local.finalized && !gimple_has_body_p (decl)
1176 && (!node->alias || !node->thunk.alias)
1177 && !node->thunk.thunk_p)
1178 cgraph_reset_node (node);
1180 if (!node->reachable
1181 && (gimple_has_body_p (decl) || node->thunk.thunk_p
1182 || (node->alias && node->thunk.alias)))
1184 if (cgraph_dump_file)
1185 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
1186 cgraph_remove_node (node);
1190 node->next_needed = NULL;
1191 gcc_assert (!node->local.finalized || node->thunk.thunk_p
1193 || gimple_has_body_p (decl));
1194 gcc_assert (node->analyzed == node->local.finalized);
1196 if (cgraph_dump_file)
1198 fprintf (cgraph_dump_file, "\n\nReclaimed ");
1199 dump_cgraph (cgraph_dump_file);
1200 dump_varpool (cgraph_dump_file);
1202 bitmap_obstack_release (NULL);
1203 first_analyzed = cgraph_nodes;
1207 /* Translate the ugly representation of aliases as alias pairs into nice
1208 representation in callgraph. We don't handle all cases yet,
1212 handle_alias_pairs (void)
1216 struct cgraph_node *target_node;
1217 struct cgraph_node *src_node;
1218 struct varpool_node *target_vnode;
1220 for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p);)
1222 if (TREE_CODE (p->decl) == FUNCTION_DECL
1223 && (target_node = cgraph_node_for_asm (p->target)) != NULL)
1225 src_node = cgraph_get_node (p->decl);
1226 if (src_node && src_node->local.finalized)
1227 cgraph_reset_node (src_node);
1228 /* Normally EXTERNAL flag is used to mark external inlines,
1229 however for aliases it seems to be allowed to use it w/o
1230 any meaning. See gcc.dg/attr-alias-3.c
1231 However for weakref we insist on EXTERNAL flag being set.
1232 See gcc.dg/attr-alias-5.c */
1233 if (DECL_EXTERNAL (p->decl))
1234 DECL_EXTERNAL (p->decl) = lookup_attribute ("weakref",
1235 DECL_ATTRIBUTES (p->decl)) != NULL;
1236 cgraph_create_function_alias (p->decl, target_node->decl);
1237 VEC_unordered_remove (alias_pair, alias_pairs, i);
1239 else if (TREE_CODE (p->decl) == VAR_DECL
1240 && (target_vnode = varpool_node_for_asm (p->target)) != NULL)
1242 /* Normally EXTERNAL flag is used to mark external inlines,
1243 however for aliases it seems to be allowed to use it w/o
1244 any meaning. See gcc.dg/attr-alias-3.c
1245 However for weakref we insist on EXTERNAL flag being set.
1246 See gcc.dg/attr-alias-5.c */
1247 if (DECL_EXTERNAL (p->decl))
1248 DECL_EXTERNAL (p->decl) = lookup_attribute ("weakref",
1249 DECL_ATTRIBUTES (p->decl)) != NULL;
1250 varpool_create_variable_alias (p->decl, target_vnode->decl);
1251 VEC_unordered_remove (alias_pair, alias_pairs, i);
1253 /* Weakrefs with target not defined in current unit are easy to handle; they
1254 behave just as external variables except we need to note the alias flag
1255 to later output the weakref pseudo op into asm file. */
1256 else if (lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) != NULL
1257 && (TREE_CODE (p->decl) == FUNCTION_DECL
1258 ? (varpool_node_for_asm (p->target) == NULL)
1259 : (cgraph_node_for_asm (p->target) == NULL)))
1261 if (TREE_CODE (p->decl) == FUNCTION_DECL)
1262 cgraph_get_create_node (p->decl)->alias = true;
1264 varpool_get_node (p->decl)->alias = true;
1265 DECL_EXTERNAL (p->decl) = 1;
1266 VEC_unordered_remove (alias_pair, alias_pairs, i);
1271 fprintf (dump_file, "Unhandled alias %s->%s\n",
1272 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (p->decl)),
1273 IDENTIFIER_POINTER (p->target));
1281 /* Analyze the whole compilation unit once it is parsed completely. */
1284 cgraph_finalize_compilation_unit (void)
1286 timevar_push (TV_CGRAPH);
1288 /* If LTO is enabled, initialize the streamer hooks needed by GIMPLE. */
1290 lto_streamer_hooks_init ();
1292 /* If we're here there's no current function anymore. Some frontends
1293 are lazy in clearing these. */
1294 current_function_decl = NULL;
1297 /* Do not skip analyzing the functions if there were errors, we
1298 miss diagnostics for following functions otherwise. */
1300 /* Emit size functions we didn't inline. */
1301 finalize_size_functions ();
1303 /* Mark alias targets necessary and emit diagnostics. */
1304 finish_aliases_1 ();
1305 handle_alias_pairs ();
1309 fprintf (stderr, "\nAnalyzing compilation unit\n");
1313 if (flag_dump_passes)
1316 /* Gimplify and lower all functions, compute reachability and
1317 remove unreachable nodes. */
1318 cgraph_analyze_functions ();
1320 /* Mark alias targets necessary and emit diagnostics. */
1321 finish_aliases_1 ();
1322 handle_alias_pairs ();
1324 /* Gimplify and lower thunks. */
1325 cgraph_analyze_functions ();
1327 /* Finally drive the pass manager. */
1330 timevar_pop (TV_CGRAPH);
1334 /* Figure out what functions we want to assemble. */
1337 cgraph_mark_functions_to_output (void)
1339 struct cgraph_node *node;
1340 #ifdef ENABLE_CHECKING
1341 bool check_same_comdat_groups = false;
1343 for (node = cgraph_nodes; node; node = node->next)
1344 gcc_assert (!node->process);
1347 for (node = cgraph_nodes; node; node = node->next)
1349 tree decl = node->decl;
1350 struct cgraph_edge *e;
1352 gcc_assert (!node->process || node->same_comdat_group);
1356 for (e = node->callers; e; e = e->next_caller)
1357 if (e->inline_failed)
1360 /* We need to output all local functions that are used and not
1361 always inlined, as well as those that are reachable from
1362 outside the current compilation unit. */
1364 && !node->thunk.thunk_p
1366 && !node->global.inlined_to
1367 && (!cgraph_only_called_directly_p (node)
1368 || ((e || ipa_ref_has_aliases_p (&node->ref_list))
1369 && node->reachable))
1370 && !TREE_ASM_WRITTEN (decl)
1371 && !DECL_EXTERNAL (decl))
1374 if (node->same_comdat_group)
1376 struct cgraph_node *next;
1377 for (next = node->same_comdat_group;
1379 next = next->same_comdat_group)
1380 if (!next->thunk.thunk_p && !next->alias)
1384 else if (node->same_comdat_group)
1386 #ifdef ENABLE_CHECKING
1387 check_same_comdat_groups = true;
1392 /* We should've reclaimed all functions that are not needed. */
1393 #ifdef ENABLE_CHECKING
1394 if (!node->global.inlined_to
1395 && gimple_has_body_p (decl)
1396 /* FIXME: in ltrans unit when offline copy is outside partition but inline copies
1397 are inside partition, we can end up not removing the body since we no longer
1398 have analyzed node pointing to it. */
1399 && !node->in_other_partition
1401 && !DECL_EXTERNAL (decl))
1403 dump_cgraph_node (stderr, node);
1404 internal_error ("failed to reclaim unneeded function");
1407 gcc_assert (node->global.inlined_to
1408 || !gimple_has_body_p (decl)
1409 || node->in_other_partition
1410 || DECL_EXTERNAL (decl));
1415 #ifdef ENABLE_CHECKING
1416 if (check_same_comdat_groups)
1417 for (node = cgraph_nodes; node; node = node->next)
1418 if (node->same_comdat_group && !node->process)
1420 tree decl = node->decl;
1421 if (!node->global.inlined_to
1422 && gimple_has_body_p (decl)
1423 /* FIXME: in ltrans unit when offline copy is outside partition but inline copies
1424 are inside partition, we can end up not removing the body since we no longer
1425 have analyzed node pointing to it. */
1426 && !node->in_other_partition
1427 && !DECL_EXTERNAL (decl))
1429 dump_cgraph_node (stderr, node);
1430 internal_error ("failed to reclaim unneeded functionin same comdat group");
1436 /* DECL is FUNCTION_DECL. Initialize datastructures so DECL is a function
1437 in lowered gimple form.
1439 Set current_function_decl and cfun to newly constructed empty function body.
1440 return basic block in the function body. */
1443 init_lowered_empty_function (tree decl)
1447 current_function_decl = decl;
1448 allocate_struct_function (decl, false);
1449 gimple_register_cfg_hooks ();
1450 init_empty_tree_cfg ();
1451 init_tree_ssa (cfun);
1452 init_ssa_operands ();
1453 cfun->gimple_df->in_ssa_p = true;
1454 DECL_INITIAL (decl) = make_node (BLOCK);
1456 DECL_SAVED_TREE (decl) = error_mark_node;
1457 cfun->curr_properties |=
1458 (PROP_gimple_lcf | PROP_gimple_leh | PROP_cfg | PROP_referenced_vars |
1459 PROP_ssa | PROP_gimple_any);
1461 /* Create BB for body of the function and connect it properly. */
1462 bb = create_basic_block (NULL, (void *) 0, ENTRY_BLOCK_PTR);
1463 make_edge (ENTRY_BLOCK_PTR, bb, 0);
1464 make_edge (bb, EXIT_BLOCK_PTR, 0);
1469 /* Adjust PTR by the constant FIXED_OFFSET, and by the vtable
1470 offset indicated by VIRTUAL_OFFSET, if that is
1471 non-null. THIS_ADJUSTING is nonzero for a this adjusting thunk and
1472 zero for a result adjusting thunk. */
1475 thunk_adjust (gimple_stmt_iterator * bsi,
1476 tree ptr, bool this_adjusting,
1477 HOST_WIDE_INT fixed_offset, tree virtual_offset)
1483 && fixed_offset != 0)
1485 stmt = gimple_build_assign
1486 (ptr, fold_build_pointer_plus_hwi_loc (input_location,
1489 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
1492 /* If there's a virtual offset, look up that value in the vtable and
1493 adjust the pointer again. */
1500 if (!vtable_entry_type)
1502 tree vfunc_type = make_node (FUNCTION_TYPE);
1503 TREE_TYPE (vfunc_type) = integer_type_node;
1504 TYPE_ARG_TYPES (vfunc_type) = NULL_TREE;
1505 layout_type (vfunc_type);
1507 vtable_entry_type = build_pointer_type (vfunc_type);
1511 create_tmp_var (build_pointer_type
1512 (build_pointer_type (vtable_entry_type)), "vptr");
1514 /* The vptr is always at offset zero in the object. */
1515 stmt = gimple_build_assign (vtabletmp,
1516 build1 (NOP_EXPR, TREE_TYPE (vtabletmp),
1518 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
1519 mark_symbols_for_renaming (stmt);
1520 find_referenced_vars_in (stmt);
1522 /* Form the vtable address. */
1523 vtabletmp2 = create_tmp_var (TREE_TYPE (TREE_TYPE (vtabletmp)),
1525 stmt = gimple_build_assign (vtabletmp2,
1526 build_simple_mem_ref (vtabletmp));
1527 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
1528 mark_symbols_for_renaming (stmt);
1529 find_referenced_vars_in (stmt);
1531 /* Find the entry with the vcall offset. */
1532 stmt = gimple_build_assign (vtabletmp2,
1533 fold_build_pointer_plus_loc (input_location,
1536 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
1538 /* Get the offset itself. */
1539 vtabletmp3 = create_tmp_var (TREE_TYPE (TREE_TYPE (vtabletmp2)),
1541 stmt = gimple_build_assign (vtabletmp3,
1542 build_simple_mem_ref (vtabletmp2));
1543 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
1544 mark_symbols_for_renaming (stmt);
1545 find_referenced_vars_in (stmt);
1547 /* Adjust the `this' pointer. */
1548 ptr = fold_build_pointer_plus_loc (input_location, ptr, vtabletmp3);
1549 ptr = force_gimple_operand_gsi (bsi, ptr, true, NULL_TREE, false,
1550 GSI_CONTINUE_LINKING);
1554 && fixed_offset != 0)
1555 /* Adjust the pointer by the constant. */
1559 if (TREE_CODE (ptr) == VAR_DECL)
1563 ptrtmp = create_tmp_var (TREE_TYPE (ptr), "ptr");
1564 stmt = gimple_build_assign (ptrtmp, ptr);
1565 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
1566 mark_symbols_for_renaming (stmt);
1567 find_referenced_vars_in (stmt);
1569 ptr = fold_build_pointer_plus_hwi_loc (input_location,
1570 ptrtmp, fixed_offset);
1573 /* Emit the statement and gimplify the adjustment expression. */
1574 ret = create_tmp_var (TREE_TYPE (ptr), "adjusted_this");
1575 stmt = gimple_build_assign (ret, ptr);
1576 mark_symbols_for_renaming (stmt);
1577 find_referenced_vars_in (stmt);
1578 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
1583 /* Produce assembler for thunk NODE. */
1586 assemble_thunk (struct cgraph_node *node)
1588 bool this_adjusting = node->thunk.this_adjusting;
1589 HOST_WIDE_INT fixed_offset = node->thunk.fixed_offset;
1590 HOST_WIDE_INT virtual_value = node->thunk.virtual_value;
1591 tree virtual_offset = NULL;
1592 tree alias = node->thunk.alias;
1593 tree thunk_fndecl = node->decl;
1594 tree a = DECL_ARGUMENTS (thunk_fndecl);
1596 current_function_decl = thunk_fndecl;
1598 /* Ensure thunks are emitted in their correct sections. */
1599 resolve_unique_section (thunk_fndecl, 0, flag_function_sections);
1602 && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
1603 virtual_value, alias))
1607 tree restype = TREE_TYPE (TREE_TYPE (thunk_fndecl));
1609 DECL_RESULT (thunk_fndecl)
1610 = build_decl (DECL_SOURCE_LOCATION (thunk_fndecl),
1611 RESULT_DECL, 0, restype);
1612 fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
1614 /* The back end expects DECL_INITIAL to contain a BLOCK, so we
1616 fn_block = make_node (BLOCK);
1617 BLOCK_VARS (fn_block) = a;
1618 DECL_INITIAL (thunk_fndecl) = fn_block;
1619 init_function_start (thunk_fndecl);
1621 assemble_start_function (thunk_fndecl, fnname);
1623 targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl,
1624 fixed_offset, virtual_value, alias);
1626 assemble_end_function (thunk_fndecl, fnname);
1627 init_insn_lengths ();
1628 free_after_compilation (cfun);
1630 TREE_ASM_WRITTEN (thunk_fndecl) = 1;
1631 node->thunk.thunk_p = false;
1632 node->analyzed = false;
1637 basic_block bb, then_bb, else_bb, return_bb;
1638 gimple_stmt_iterator bsi;
1644 VEC(tree, heap) *vargs;
1649 DECL_IGNORED_P (thunk_fndecl) = 1;
1650 bitmap_obstack_initialize (NULL);
1652 if (node->thunk.virtual_offset_p)
1653 virtual_offset = size_int (virtual_value);
1655 /* Build the return declaration for the function. */
1656 restype = TREE_TYPE (TREE_TYPE (thunk_fndecl));
1657 if (DECL_RESULT (thunk_fndecl) == NULL_TREE)
1659 resdecl = build_decl (input_location, RESULT_DECL, 0, restype);
1660 DECL_ARTIFICIAL (resdecl) = 1;
1661 DECL_IGNORED_P (resdecl) = 1;
1662 DECL_RESULT (thunk_fndecl) = resdecl;
1665 resdecl = DECL_RESULT (thunk_fndecl);
1667 bb = then_bb = else_bb = return_bb = init_lowered_empty_function (thunk_fndecl);
1669 bsi = gsi_start_bb (bb);
1671 /* Build call to the function being thunked. */
1672 if (!VOID_TYPE_P (restype))
1674 if (!is_gimple_reg_type (restype))
1677 add_local_decl (cfun, restmp);
1678 BLOCK_VARS (DECL_INITIAL (current_function_decl)) = restmp;
1681 restmp = create_tmp_var_raw (restype, "retval");
1684 for (arg = a; arg; arg = DECL_CHAIN (arg))
1686 vargs = VEC_alloc (tree, heap, nargs);
1688 VEC_quick_push (tree, vargs,
1693 VEC_quick_push (tree, vargs, a);
1694 for (i = 1, arg = DECL_CHAIN (a); i < nargs; i++, arg = DECL_CHAIN (arg))
1695 VEC_quick_push (tree, vargs, arg);
1696 call = gimple_build_call_vec (build_fold_addr_expr_loc (0, alias), vargs);
1697 VEC_free (tree, heap, vargs);
1698 gimple_call_set_from_thunk (call, true);
1700 gimple_call_set_lhs (call, restmp);
1701 gsi_insert_after (&bsi, call, GSI_NEW_STMT);
1702 mark_symbols_for_renaming (call);
1703 find_referenced_vars_in (call);
1706 if (restmp && !this_adjusting)
1708 tree true_label = NULL_TREE;
1710 if (TREE_CODE (TREE_TYPE (restmp)) == POINTER_TYPE)
1713 /* If the return type is a pointer, we need to
1714 protect against NULL. We know there will be an
1715 adjustment, because that's why we're emitting a
1717 then_bb = create_basic_block (NULL, (void *) 0, bb);
1718 return_bb = create_basic_block (NULL, (void *) 0, then_bb);
1719 else_bb = create_basic_block (NULL, (void *) 0, else_bb);
1720 remove_edge (single_succ_edge (bb));
1721 true_label = gimple_block_label (then_bb);
1722 stmt = gimple_build_cond (NE_EXPR, restmp,
1723 build_zero_cst (TREE_TYPE (restmp)),
1724 NULL_TREE, NULL_TREE);
1725 gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
1726 make_edge (bb, then_bb, EDGE_TRUE_VALUE);
1727 make_edge (bb, else_bb, EDGE_FALSE_VALUE);
1728 make_edge (return_bb, EXIT_BLOCK_PTR, 0);
1729 make_edge (then_bb, return_bb, EDGE_FALLTHRU);
1730 make_edge (else_bb, return_bb, EDGE_FALLTHRU);
1731 bsi = gsi_last_bb (then_bb);
1734 restmp = thunk_adjust (&bsi, restmp, /*this_adjusting=*/0,
1735 fixed_offset, virtual_offset);
1739 bsi = gsi_last_bb (else_bb);
1740 stmt = gimple_build_assign (restmp,
1741 build_zero_cst (TREE_TYPE (restmp)));
1742 gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
1743 bsi = gsi_last_bb (return_bb);
1747 gimple_call_set_tail (call, true);
1749 /* Build return value. */
1750 ret = gimple_build_return (restmp);
1751 gsi_insert_after (&bsi, ret, GSI_NEW_STMT);
1753 delete_unreachable_blocks ();
1754 update_ssa (TODO_update_ssa);
1756 /* Since we want to emit the thunk, we explicitly mark its name as
1758 node->thunk.thunk_p = false;
1759 cgraph_node_remove_callees (node);
1760 cgraph_add_new_function (thunk_fndecl, true);
1761 bitmap_obstack_release (NULL);
1763 current_function_decl = NULL;
1768 /* Assemble thunks and aliases asociated to NODE. */
1771 assemble_thunks_and_aliases (struct cgraph_node *node)
1773 struct cgraph_edge *e;
1775 struct ipa_ref *ref;
1777 for (e = node->callers; e;)
1778 if (e->caller->thunk.thunk_p)
1780 struct cgraph_node *thunk = e->caller;
1783 assemble_thunks_and_aliases (thunk);
1784 assemble_thunk (thunk);
1788 for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref); i++)
1789 if (ref->use == IPA_REF_ALIAS)
1791 struct cgraph_node *alias = ipa_ref_refering_node (ref);
1792 bool saved_written = TREE_ASM_WRITTEN (alias->thunk.alias);
1794 /* Force assemble_alias to really output the alias this time instead
1795 of buffering it in same alias pairs. */
1796 TREE_ASM_WRITTEN (alias->thunk.alias) = 1;
1797 assemble_alias (alias->decl,
1798 DECL_ASSEMBLER_NAME (alias->thunk.alias));
1799 assemble_thunks_and_aliases (alias);
1800 TREE_ASM_WRITTEN (alias->thunk.alias) = saved_written;
1804 /* Expand function specified by NODE. */
1807 cgraph_expand_function (struct cgraph_node *node)
1809 tree decl = node->decl;
1811 /* We ought to not compile any inline clones. */
1812 gcc_assert (!node->global.inlined_to);
1814 announce_function (decl);
1816 gcc_assert (node->lowered);
1818 /* Generate RTL for the body of DECL. */
1819 tree_rest_of_compilation (decl);
1821 /* Make sure that BE didn't give up on compiling. */
1822 gcc_assert (TREE_ASM_WRITTEN (decl));
1823 current_function_decl = NULL;
1824 gcc_assert (!cgraph_preserve_function_body_p (node));
1826 /* It would make a lot more sense to output thunks before function body to get more
1827 forward and lest backwarding jumps. This is however would need solving problem
1828 with comdats. See PR48668. Also aliases must come after function itself to
1829 make one pass assemblers, like one on AIX happy. See PR 50689.
1830 FIXME: Perhaps thunks should be move before function IFF they are not in comdat
1832 assemble_thunks_and_aliases (node);
1833 cgraph_release_function_body (node);
1834 /* Eliminate all call edges. This is important so the GIMPLE_CALL no longer
1835 points to the dead function body. */
1836 cgraph_node_remove_callees (node);
1838 cgraph_function_flags_ready = true;
1841 /* Return true when CALLER_DECL should be inlined into CALLEE_DECL. */
1844 cgraph_inline_p (struct cgraph_edge *e, cgraph_inline_failed_t *reason)
1846 *reason = e->inline_failed;
1847 return !e->inline_failed;
1852 /* Expand all functions that must be output.
1854 Attempt to topologically sort the nodes so function is output when
1855 all called functions are already assembled to allow data to be
1856 propagated across the callgraph. Use a stack to get smaller distance
1857 between a function and its callees (later we may choose to use a more
1858 sophisticated algorithm for function reordering; we will likely want
1859 to use subsections to make the output functions appear in top-down
1863 cgraph_expand_all_functions (void)
1865 struct cgraph_node *node;
1866 struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
1867 int order_pos, new_order_pos = 0;
1870 order_pos = ipa_reverse_postorder (order);
1871 gcc_assert (order_pos == cgraph_n_nodes);
1873 /* Garbage collector may remove inline clones we eliminate during
1874 optimization. So we must be sure to not reference them. */
1875 for (i = 0; i < order_pos; i++)
1876 if (order[i]->process)
1877 order[new_order_pos++] = order[i];
1879 for (i = new_order_pos - 1; i >= 0; i--)
1884 gcc_assert (node->reachable);
1886 cgraph_expand_function (node);
1889 cgraph_process_new_functions ();
1895 /* This is used to sort the node types by the cgraph order number. */
1897 enum cgraph_order_sort_kind
1899 ORDER_UNDEFINED = 0,
1905 struct cgraph_order_sort
1907 enum cgraph_order_sort_kind kind;
1910 struct cgraph_node *f;
1911 struct varpool_node *v;
1912 struct cgraph_asm_node *a;
1916 /* Output all functions, variables, and asm statements in the order
1917 according to their order fields, which is the order in which they
1918 appeared in the file. This implements -fno-toplevel-reorder. In
1919 this mode we may output functions and variables which don't really
1920 need to be output. */
1923 cgraph_output_in_order (void)
1926 struct cgraph_order_sort *nodes;
1928 struct cgraph_node *pf;
1929 struct varpool_node *pv;
1930 struct cgraph_asm_node *pa;
1933 nodes = XCNEWVEC (struct cgraph_order_sort, max);
1935 varpool_analyze_pending_decls ();
1937 for (pf = cgraph_nodes; pf; pf = pf->next)
1939 if (pf->process && !pf->thunk.thunk_p && !pf->alias)
1942 gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
1943 nodes[i].kind = ORDER_FUNCTION;
1948 for (pv = varpool_nodes_queue; pv; pv = pv->next_needed)
1951 gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
1952 nodes[i].kind = ORDER_VAR;
1956 for (pa = cgraph_asm_nodes; pa; pa = pa->next)
1959 gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
1960 nodes[i].kind = ORDER_ASM;
1964 /* In toplevel reorder mode we output all statics; mark them as needed. */
1965 for (i = 0; i < max; ++i)
1967 if (nodes[i].kind == ORDER_VAR)
1969 varpool_mark_needed_node (nodes[i].u.v);
1972 varpool_empty_needed_queue ();
1974 for (i = 0; i < max; ++i)
1975 if (nodes[i].kind == ORDER_VAR)
1976 varpool_finalize_named_section_flags (nodes[i].u.v);
1978 for (i = 0; i < max; ++i)
1980 switch (nodes[i].kind)
1982 case ORDER_FUNCTION:
1983 nodes[i].u.f->process = 0;
1984 cgraph_expand_function (nodes[i].u.f);
1988 varpool_assemble_decl (nodes[i].u.v);
1992 assemble_asm (nodes[i].u.a->asm_str);
1995 case ORDER_UNDEFINED:
2003 cgraph_asm_nodes = NULL;
2007 /* Return true when function body of DECL still needs to be kept around
2008 for later re-use. */
2010 cgraph_preserve_function_body_p (struct cgraph_node *node)
2012 gcc_assert (cgraph_global_info_ready);
2013 gcc_assert (!node->alias && !node->thunk.thunk_p);
2015 /* Look if there is any clone around. */
2025 current_function_decl = NULL;
2026 gimple_register_cfg_hooks ();
2027 bitmap_obstack_initialize (NULL);
2029 invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_START, NULL);
2033 execute_ipa_pass_list (all_small_ipa_passes);
2038 /* We never run removal of unreachable nodes after early passes. This is
2039 because TODO is run before the subpasses. It is important to remove
2040 the unreachable functions to save works at IPA level and to get LTO
2041 symbol tables right. */
2042 cgraph_remove_unreachable_nodes (true, cgraph_dump_file);
2044 /* If pass_all_early_optimizations was not scheduled, the state of
2045 the cgraph will not be properly updated. Update it now. */
2046 if (cgraph_state < CGRAPH_STATE_IPA_SSA)
2047 cgraph_state = CGRAPH_STATE_IPA_SSA;
2051 /* Generate coverage variables and constructors. */
2054 /* Process new functions added. */
2056 current_function_decl = NULL;
2057 cgraph_process_new_functions ();
2059 execute_ipa_summary_passes
2060 ((struct ipa_opt_pass_d *) all_regular_ipa_passes);
2063 /* Some targets need to handle LTO assembler output specially. */
2064 if (flag_generate_lto)
2065 targetm.asm_out.lto_start ();
2067 execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_lto_gen_passes);
2070 ipa_write_summaries ();
2072 if (flag_generate_lto)
2073 targetm.asm_out.lto_end ();
2075 if (!flag_ltrans && (in_lto_p || !flag_lto || flag_fat_lto_objects))
2076 execute_ipa_pass_list (all_regular_ipa_passes);
2077 invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_END, NULL);
2079 bitmap_obstack_release (NULL);
2083 /* Return string alias is alias of. */
2086 get_alias_symbol (tree decl)
2088 tree alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl));
2089 return get_identifier (TREE_STRING_POINTER
2090 (TREE_VALUE (TREE_VALUE (alias))));
2094 /* Weakrefs may be associated to external decls and thus not output
2095 at expansion time. Emit all neccesary aliases. */
2098 output_weakrefs (void)
2100 struct cgraph_node *node;
2101 struct varpool_node *vnode;
2102 for (node = cgraph_nodes; node; node = node->next)
2103 if (node->alias && DECL_EXTERNAL (node->decl)
2104 && !TREE_ASM_WRITTEN (node->decl)
2105 && lookup_attribute ("weakref", DECL_ATTRIBUTES (node->decl)))
2106 assemble_alias (node->decl,
2107 node->thunk.alias ? DECL_ASSEMBLER_NAME (node->thunk.alias)
2108 : get_alias_symbol (node->decl));
2109 for (vnode = varpool_nodes; vnode; vnode = vnode->next)
2110 if (vnode->alias && DECL_EXTERNAL (vnode->decl)
2111 && !TREE_ASM_WRITTEN (vnode->decl)
2112 && lookup_attribute ("weakref", DECL_ATTRIBUTES (vnode->decl)))
2113 assemble_alias (vnode->decl,
2114 vnode->alias_of ? DECL_ASSEMBLER_NAME (vnode->alias_of)
2115 : get_alias_symbol (vnode->decl));
2119 /* Perform simple optimizations based on callgraph. */
2122 cgraph_optimize (void)
2127 #ifdef ENABLE_CHECKING
2131 /* Frontend may output common variables after the unit has been finalized.
2132 It is safe to deal with them here as they are always zero initialized. */
2133 varpool_analyze_pending_decls ();
2135 timevar_push (TV_CGRAPHOPT);
2136 if (pre_ipa_mem_report)
2138 fprintf (stderr, "Memory consumption before IPA\n");
2139 dump_memory_report (false);
2142 fprintf (stderr, "Performing interprocedural optimizations\n");
2143 cgraph_state = CGRAPH_STATE_IPA;
2145 /* Don't run the IPA passes if there was any error or sorry messages. */
2149 /* Do nothing else if any IPA pass found errors or if we are just streaming LTO. */
2151 || (!in_lto_p && flag_lto && !flag_fat_lto_objects))
2153 timevar_pop (TV_CGRAPHOPT);
2157 /* This pass remove bodies of extern inline functions we never inlined.
2158 Do this later so other IPA passes see what is really going on. */
2159 cgraph_remove_unreachable_nodes (false, dump_file);
2160 cgraph_global_info_ready = true;
2161 if (cgraph_dump_file)
2163 fprintf (cgraph_dump_file, "Optimized ");
2164 dump_cgraph (cgraph_dump_file);
2165 dump_varpool (cgraph_dump_file);
2167 if (post_ipa_mem_report)
2169 fprintf (stderr, "Memory consumption after IPA\n");
2170 dump_memory_report (false);
2172 timevar_pop (TV_CGRAPHOPT);
2174 /* Output everything. */
2175 (*debug_hooks->assembly_start) ();
2177 fprintf (stderr, "Assembling functions:\n");
2178 #ifdef ENABLE_CHECKING
2182 cgraph_materialize_all_clones ();
2183 bitmap_obstack_initialize (NULL);
2184 execute_ipa_pass_list (all_late_ipa_passes);
2185 cgraph_remove_unreachable_nodes (true, dump_file);
2186 #ifdef ENABLE_CHECKING
2189 bitmap_obstack_release (NULL);
2190 cgraph_mark_functions_to_output ();
2193 cgraph_state = CGRAPH_STATE_EXPANSION;
2194 if (!flag_toplevel_reorder)
2195 cgraph_output_in_order ();
2198 cgraph_output_pending_asms ();
2200 cgraph_expand_all_functions ();
2201 varpool_remove_unreferenced_decls ();
2203 varpool_assemble_pending_decls ();
2206 cgraph_process_new_functions ();
2207 cgraph_state = CGRAPH_STATE_FINISHED;
2209 if (cgraph_dump_file)
2211 fprintf (cgraph_dump_file, "\nFinal ");
2212 dump_cgraph (cgraph_dump_file);
2213 dump_varpool (cgraph_dump_file);
2215 #ifdef ENABLE_CHECKING
2217 /* Double check that all inline clones are gone and that all
2218 function bodies have been released from memory. */
2221 struct cgraph_node *node;
2222 bool error_found = false;
2224 for (node = cgraph_nodes; node; node = node->next)
2226 && (node->global.inlined_to
2227 || gimple_has_body_p (node->decl)))
2230 dump_cgraph_node (stderr, node);
2233 internal_error ("nodes with unreleased memory found");
2241 if (!cgraph_dump_file)
2242 cgraph_dump_file = dump_begin (TDI_cgraph, NULL);
2245 /* The edges representing the callers of the NEW_VERSION node were
2246 fixed by cgraph_function_versioning (), now the call_expr in their
2247 respective tree code should be updated to call the NEW_VERSION. */
2250 update_call_expr (struct cgraph_node *new_version)
2252 struct cgraph_edge *e;
2254 gcc_assert (new_version);
2256 /* Update the call expr on the edges to call the new version. */
2257 for (e = new_version->callers; e; e = e->next_caller)
2259 struct function *inner_function = DECL_STRUCT_FUNCTION (e->caller->decl);
2260 gimple_call_set_fndecl (e->call_stmt, new_version->decl);
2261 maybe_clean_eh_stmt_fn (inner_function, e->call_stmt);
2266 /* Create a new cgraph node which is the new version of
2267 OLD_VERSION node. REDIRECT_CALLERS holds the callers
2268 edges which should be redirected to point to
2269 NEW_VERSION. ALL the callees edges of OLD_VERSION
2270 are cloned to the new version node. Return the new
2273 If non-NULL BLOCK_TO_COPY determine what basic blocks
2274 was copied to prevent duplications of calls that are dead
2277 struct cgraph_node *
2278 cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
2280 VEC(cgraph_edge_p,heap) *redirect_callers,
2283 struct cgraph_node *new_version;
2284 struct cgraph_edge *e;
2287 gcc_assert (old_version);
2289 new_version = cgraph_create_node (new_decl);
2291 new_version->analyzed = old_version->analyzed;
2292 new_version->local = old_version->local;
2293 new_version->local.externally_visible = false;
2294 new_version->local.local = true;
2295 new_version->global = old_version->global;
2296 new_version->rtl = old_version->rtl;
2297 new_version->reachable = true;
2298 new_version->count = old_version->count;
2300 for (e = old_version->callees; e; e=e->next_callee)
2302 || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index))
2303 cgraph_clone_edge (e, new_version, e->call_stmt,
2304 e->lto_stmt_uid, REG_BR_PROB_BASE,
2307 for (e = old_version->indirect_calls; e; e=e->next_callee)
2309 || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index))
2310 cgraph_clone_edge (e, new_version, e->call_stmt,
2311 e->lto_stmt_uid, REG_BR_PROB_BASE,
2314 FOR_EACH_VEC_ELT (cgraph_edge_p, redirect_callers, i, e)
2316 /* Redirect calls to the old version node to point to its new
2318 cgraph_redirect_edge_callee (e, new_version);
2321 cgraph_call_node_duplication_hooks (old_version, new_version);
2326 /* Perform function versioning.
2327 Function versioning includes copying of the tree and
2328 a callgraph update (creating a new cgraph node and updating
2329 its callees and callers).
2331 REDIRECT_CALLERS varray includes the edges to be redirected
2334 TREE_MAP is a mapping of tree nodes we want to replace with
2335 new ones (according to results of prior analysis).
2336 OLD_VERSION_NODE is the node that is versioned.
2338 If non-NULL ARGS_TO_SKIP determine function parameters to remove
2340 If SKIP_RETURN is true, the new version will return void.
2341 If non-NULL BLOCK_TO_COPY determine what basic blocks to copy.
2342 If non_NULL NEW_ENTRY determine new entry BB of the clone.
2344 Return the new version's cgraph node. */
2346 struct cgraph_node *
2347 cgraph_function_versioning (struct cgraph_node *old_version_node,
2348 VEC(cgraph_edge_p,heap) *redirect_callers,
2349 VEC (ipa_replace_map_p,gc)* tree_map,
2350 bitmap args_to_skip,
2353 basic_block new_entry_block,
2354 const char *clone_name)
2356 tree old_decl = old_version_node->decl;
2357 struct cgraph_node *new_version_node = NULL;
2360 if (!tree_versionable_function_p (old_decl))
2363 gcc_assert (old_version_node->local.can_change_signature || !args_to_skip);
2365 /* Make a new FUNCTION_DECL tree node for the new version. */
2366 if (!args_to_skip && !skip_return)
2367 new_decl = copy_node (old_decl);
2370 = build_function_decl_skip_args (old_decl, args_to_skip, skip_return);
2372 /* Generate a new name for the new version. */
2373 DECL_NAME (new_decl) = clone_function_name (old_decl, clone_name);
2374 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
2375 SET_DECL_RTL (new_decl, NULL);
2377 /* When the old decl was a con-/destructor make sure the clone isn't. */
2378 DECL_STATIC_CONSTRUCTOR(new_decl) = 0;
2379 DECL_STATIC_DESTRUCTOR(new_decl) = 0;
2381 /* Create the new version's call-graph node.
2382 and update the edges of the new node. */
2384 cgraph_copy_node_for_versioning (old_version_node, new_decl,
2385 redirect_callers, bbs_to_copy);
2387 /* Copy the OLD_VERSION_NODE function tree to the new version. */
2388 tree_function_versioning (old_decl, new_decl, tree_map, false, args_to_skip,
2389 skip_return, bbs_to_copy, new_entry_block);
2391 /* Update the new version's properties.
2392 Make The new version visible only within this translation unit. Make sure
2393 that is not weak also.
2394 ??? We cannot use COMDAT linkage because there is no
2395 ABI support for this. */
2396 cgraph_make_decl_local (new_version_node->decl);
2397 DECL_VIRTUAL_P (new_version_node->decl) = 0;
2398 new_version_node->local.externally_visible = 0;
2399 new_version_node->local.local = 1;
2400 new_version_node->lowered = true;
2402 /* Update the call_expr on the edges to call the new version node. */
2403 update_call_expr (new_version_node);
2405 cgraph_call_function_insertion_hooks (new_version_node);
2406 return new_version_node;
2409 /* Given virtual clone, turn it into actual clone. */
2411 cgraph_materialize_clone (struct cgraph_node *node)
2413 bitmap_obstack_initialize (NULL);
2414 node->former_clone_of = node->clone_of->decl;
2415 if (node->clone_of->former_clone_of)
2416 node->former_clone_of = node->clone_of->former_clone_of;
2417 /* Copy the OLD_VERSION_NODE function tree to the new version. */
2418 tree_function_versioning (node->clone_of->decl, node->decl,
2419 node->clone.tree_map, true,
2420 node->clone.args_to_skip, false,
2422 if (cgraph_dump_file)
2424 dump_function_to_file (node->clone_of->decl, cgraph_dump_file, dump_flags);
2425 dump_function_to_file (node->decl, cgraph_dump_file, dump_flags);
2428 /* Function is no longer clone. */
2429 if (node->next_sibling_clone)
2430 node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone;
2431 if (node->prev_sibling_clone)
2432 node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
2434 node->clone_of->clones = node->next_sibling_clone;
2435 node->next_sibling_clone = NULL;
2436 node->prev_sibling_clone = NULL;
2437 if (!node->clone_of->analyzed && !node->clone_of->clones)
2439 cgraph_release_function_body (node->clone_of);
2440 cgraph_node_remove_callees (node->clone_of);
2441 ipa_remove_all_references (&node->clone_of->ref_list);
2443 node->clone_of = NULL;
2444 bitmap_obstack_release (NULL);
2447 /* If necessary, change the function declaration in the call statement
2448 associated with E so that it corresponds to the edge callee. */
2451 cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
2453 tree decl = gimple_call_fndecl (e->call_stmt);
2455 gimple_stmt_iterator gsi;
2456 #ifdef ENABLE_CHECKING
2457 struct cgraph_node *node;
2460 if (e->indirect_unknown_callee
2461 || decl == e->callee->decl)
2462 return e->call_stmt;
2464 #ifdef ENABLE_CHECKING
2467 node = cgraph_get_node (decl);
2468 gcc_assert (!node || !node->clone.combined_args_to_skip);
2472 if (cgraph_dump_file)
2474 fprintf (cgraph_dump_file, "updating call of %s/%i -> %s/%i: ",
2475 cgraph_node_name (e->caller), e->caller->uid,
2476 cgraph_node_name (e->callee), e->callee->uid);
2477 print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags);
2478 if (e->callee->clone.combined_args_to_skip)
2480 fprintf (cgraph_dump_file, " combined args to skip: ");
2481 dump_bitmap (cgraph_dump_file,
2482 e->callee->clone.combined_args_to_skip);
2486 if (e->callee->clone.combined_args_to_skip)
2491 = gimple_call_copy_skip_args (e->call_stmt,
2492 e->callee->clone.combined_args_to_skip);
2493 gimple_call_set_fndecl (new_stmt, e->callee->decl);
2495 if (gimple_vdef (new_stmt)
2496 && TREE_CODE (gimple_vdef (new_stmt)) == SSA_NAME)
2497 SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
2499 gsi = gsi_for_stmt (e->call_stmt);
2500 gsi_replace (&gsi, new_stmt, false);
2501 /* We need to defer cleaning EH info on the new statement to
2502 fixup-cfg. We may not have dominator information at this point
2503 and thus would end up with unreachable blocks and have no way
2504 to communicate that we need to run CFG cleanup then. */
2505 lp_nr = lookup_stmt_eh_lp (e->call_stmt);
2508 remove_stmt_from_eh_lp (e->call_stmt);
2509 add_stmt_to_eh_lp (new_stmt, lp_nr);
2514 new_stmt = e->call_stmt;
2515 gimple_call_set_fndecl (new_stmt, e->callee->decl);
2516 update_stmt (new_stmt);
2519 cgraph_set_call_stmt_including_clones (e->caller, e->call_stmt, new_stmt);
2521 if (cgraph_dump_file)
2523 fprintf (cgraph_dump_file, " updated to:");
2524 print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags);
2529 /* Once all functions from compilation unit are in memory, produce all clones
2530 and update all calls. We might also do this on demand if we don't want to
2531 bring all functions to memory prior compilation, but current WHOPR
2532 implementation does that and it is is bit easier to keep everything right in
2535 cgraph_materialize_all_clones (void)
2537 struct cgraph_node *node;
2538 bool stabilized = false;
2540 if (cgraph_dump_file)
2541 fprintf (cgraph_dump_file, "Materializing clones\n");
2542 #ifdef ENABLE_CHECKING
2546 /* We can also do topological order, but number of iterations should be
2547 bounded by number of IPA passes since single IPA pass is probably not
2548 going to create clones of clones it created itself. */
2552 for (node = cgraph_nodes; node; node = node->next)
2554 if (node->clone_of && node->decl != node->clone_of->decl
2555 && !gimple_has_body_p (node->decl))
2557 if (gimple_has_body_p (node->clone_of->decl))
2559 if (cgraph_dump_file)
2561 fprintf (cgraph_dump_file, "cloning %s to %s\n",
2562 cgraph_node_name (node->clone_of),
2563 cgraph_node_name (node));
2564 if (node->clone.tree_map)
2567 fprintf (cgraph_dump_file, " replace map: ");
2568 for (i = 0; i < VEC_length (ipa_replace_map_p,
2569 node->clone.tree_map);
2572 struct ipa_replace_map *replace_info;
2573 replace_info = VEC_index (ipa_replace_map_p,
2574 node->clone.tree_map,
2576 print_generic_expr (cgraph_dump_file, replace_info->old_tree, 0);
2577 fprintf (cgraph_dump_file, " -> ");
2578 print_generic_expr (cgraph_dump_file, replace_info->new_tree, 0);
2579 fprintf (cgraph_dump_file, "%s%s;",
2580 replace_info->replace_p ? "(replace)":"",
2581 replace_info->ref_p ? "(ref)":"");
2583 fprintf (cgraph_dump_file, "\n");
2585 if (node->clone.args_to_skip)
2587 fprintf (cgraph_dump_file, " args_to_skip: ");
2588 dump_bitmap (cgraph_dump_file, node->clone.args_to_skip);
2590 if (node->clone.args_to_skip)
2592 fprintf (cgraph_dump_file, " combined_args_to_skip:");
2593 dump_bitmap (cgraph_dump_file, node->clone.combined_args_to_skip);
2596 cgraph_materialize_clone (node);
2602 for (node = cgraph_nodes; node; node = node->next)
2603 if (!node->analyzed && node->callees)
2604 cgraph_node_remove_callees (node);
2605 if (cgraph_dump_file)
2606 fprintf (cgraph_dump_file, "Materialization Call site updates done.\n");
2607 #ifdef ENABLE_CHECKING
2610 cgraph_remove_unreachable_nodes (false, cgraph_dump_file);
2613 #include "gt-cgraphunit.h"