1 /* Callgraph based intraprocedural optimizations.
2 Copyright (C) 2003 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
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
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, 59 Temple Place - Suite 330, Boston, MA
24 #include "coretypes.h"
27 #include "tree-inline.h"
28 #include "langhooks.h"
36 #include "diagnostic.h"
42 #define INSNS_PER_CALL 10
44 static void cgraph_expand_functions (void);
45 static void cgraph_mark_functions_to_output (void);
46 static void cgraph_expand_function (struct cgraph_node *);
47 static tree record_call_1 (tree *, int *, void *);
48 static void cgraph_mark_local_functions (void);
49 static void cgraph_optimize_function (struct cgraph_node *);
51 /* Statistics we collect about inlining algorithm. */
52 static int ncalls_inlined;
53 static int nfunctions_inlined;
54 static int initial_insns;
55 static int overall_insns;
57 /* Analyze function once it is parsed. Set up the local information
58 available - create cgraph edges for function calls via BODY. */
61 cgraph_finalize_function (tree decl, tree body ATTRIBUTE_UNUSED)
63 struct cgraph_node *node = cgraph_node (decl);
66 node->local.finalized = true;
68 /* Function now has DECL_SAVED_TREE set. Enqueue it into cgraph_nodes_queue
71 cgraph_mark_needed_node (node, 0);
72 if (/* Externally visible functions must be output. The exception are
73 COMDAT functions that must be output only when they are needed.
74 Similarly are handled deferred functions and
75 external functions (GCC extension "extern inline") */
76 (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
77 /* ??? Constructors and destructors not called otherwise can be inlined
78 into single construction/destruction function per section to save some
79 resources. For now just mark it as reachable. */
80 || DECL_STATIC_CONSTRUCTOR (decl)
81 || DECL_STATIC_DESTRUCTOR (decl)
82 /* Function whose name is output to the assembler file must be produced.
83 It is possible to assemble the name later after finalizing the function
84 and the fact is noticed in assemble_name then. */
85 || (DECL_ASSEMBLER_NAME_SET_P (decl)
86 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
87 || lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
89 cgraph_mark_needed_node (node, 1);
92 (*debug_hooks->deferred_inline_function) (decl);
95 /* Walk tree and record all calls. Called via walk_tree. */
97 record_call_1 (tree *tp, int *walk_subtrees, void *data)
99 if (TREE_CODE (*tp) == VAR_DECL && TREE_STATIC (*tp))
100 cgraph_varpool_mark_needed_node (cgraph_varpool_node (*tp));
101 /* Record dereferences to the functions. This makes the functions
102 reachable unconditionally. */
103 else if (TREE_CODE (*tp) == ADDR_EXPR)
105 tree decl = TREE_OPERAND (*tp, 0);
106 if (TREE_CODE (decl) == FUNCTION_DECL)
107 cgraph_mark_needed_node (cgraph_node (decl), 1);
109 else if (TREE_CODE (*tp) == CALL_EXPR)
111 tree decl = get_callee_fndecl (*tp);
112 if (decl && TREE_CODE (decl) == FUNCTION_DECL)
114 if (DECL_BUILT_IN (decl))
116 cgraph_record_call (data, decl);
118 /* When we see a function call, we don't want to look at the
119 function reference in the ADDR_EXPR that is hanging from
120 the CALL_EXPR we're examining here, because we would
121 conclude incorrectly that the function's address could be
122 taken by something that is not a function call. So only
123 walk the function parameter list, skip the other subtrees. */
125 walk_tree (&TREE_OPERAND (*tp, 1), record_call_1, data, NULL);
129 /* Save some cycles by not walking types and declaration as we won't find anything
130 usefull there anyway. */
131 if (DECL_P (*tp) || TYPE_P (*tp))
136 /* Create cgraph edges for function calls inside BODY from DECL. */
139 cgraph_create_edges (tree decl, tree body)
141 /* The nodes we're interested in are never shared, so walk
142 the tree ignoring duplicates. */
143 walk_tree_without_duplicates (&body, record_call_1, decl);
146 /* Analyze the function scheduled to be output. */
148 cgraph_analyze_function (struct cgraph_node *node)
150 tree decl = node->decl;
152 if (lang_hooks.callgraph.lower_function)
153 (*lang_hooks.callgraph.lower_function) (decl);
155 current_function_decl = node->decl;
157 /* First kill forward declaration so reverse inlining works properly. */
158 cgraph_create_edges (decl, DECL_SAVED_TREE (decl));
160 node->local.inlinable = tree_inlinable_function_p (decl);
161 if (!DECL_ESTIMATED_INSNS (decl))
162 DECL_ESTIMATED_INSNS (decl)
163 = (*lang_hooks.tree_inlining.estimate_num_insns) (decl);
164 node->local.self_insns = DECL_ESTIMATED_INSNS (decl);
165 if (node->local.inlinable)
166 node->local.disregard_inline_limits
167 = (*lang_hooks.tree_inlining.disregard_inline_limits) (decl);
169 /* Inlining characteristics are maintained by the cgraph_mark_inline. */
170 node->global.insns = node->local.self_insns;
171 if (!DECL_EXTERNAL (node->decl))
173 node->global.cloned_times = 1;
174 node->global.will_be_output = true;
177 node->lowered = true;
180 /* Analyze the whole compilation unit once it is parsed completely. */
183 cgraph_finalize_compilation_unit (void)
185 struct cgraph_node *node;
187 cgraph_varpool_assemble_pending_decls ();
189 fprintf (stderr, "\nAnalyzing compilation unit\n");
191 timevar_push (TV_CGRAPH);
192 if (cgraph_dump_file)
194 fprintf (cgraph_dump_file, "\nInitial entry points:");
195 for (node = cgraph_nodes; node; node = node->next)
196 if (node->needed && DECL_SAVED_TREE (node->decl))
197 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
198 fprintf (cgraph_dump_file, "\n");
201 /* Propagate reachability flag and lower representation of all reachable
202 functions. In the future, lowering will introduce new functions and
203 new entry points on the way (by template instantiation and virtual
204 method table generation for instance). */
205 while (cgraph_nodes_queue)
207 struct cgraph_edge *edge;
208 tree decl = cgraph_nodes_queue->decl;
210 node = cgraph_nodes_queue;
211 cgraph_nodes_queue = cgraph_nodes_queue->next_needed;
213 if (node->lowered || !node->reachable || !DECL_SAVED_TREE (decl))
216 cgraph_analyze_function (node);
217 for (edge = node->callees; edge; edge = edge->next_callee)
219 if (!edge->callee->reachable)
220 cgraph_mark_needed_node (edge->callee, 0);
222 cgraph_varpool_assemble_pending_decls ();
224 /* Collect entry points to the unit. */
226 if (cgraph_dump_file)
228 fprintf (cgraph_dump_file, "\nUnit entry points:");
229 for (node = cgraph_nodes; node; node = node->next)
230 if (node->needed && DECL_SAVED_TREE (node->decl))
231 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
232 fprintf (cgraph_dump_file, "\n");
233 dump_cgraph (cgraph_dump_file);
236 if (cgraph_dump_file)
237 fprintf (cgraph_dump_file, "\nReclaiming functions:");
239 for (node = cgraph_nodes; node; node = node->next)
241 tree decl = node->decl;
243 if (!node->reachable && DECL_SAVED_TREE (decl))
245 cgraph_remove_node (node);
246 if (cgraph_dump_file)
247 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
250 if (cgraph_dump_file)
251 fprintf (cgraph_dump_file, "\n");
253 timevar_pop (TV_CGRAPH);
256 /* Figure out what functions we want to assemble. */
259 cgraph_mark_functions_to_output (void)
261 struct cgraph_node *node;
263 for (node = cgraph_nodes; node; node = node->next)
265 tree decl = node->decl;
266 struct cgraph_edge *e;
270 for (e = node->callers; e; e = e->next_caller)
274 /* We need to output all local functions that are used and not
275 always inlined, as well as those that are reachable from
276 outside the current compilation unit. */
277 if (DECL_SAVED_TREE (decl)
279 || (e && node->reachable))
280 && !TREE_ASM_WRITTEN (decl) && !node->origin
281 && !DECL_EXTERNAL (decl))
286 /* Optimize the function before expansion. */
289 cgraph_optimize_function (struct cgraph_node *node)
291 tree decl = node->decl;
293 timevar_push (TV_INTEGRATION);
294 /* optimize_inline_calls avoids inlining of current_function_decl. */
295 current_function_decl = 0;
296 if (flag_inline_trees)
297 optimize_inline_calls (decl);
300 for (node = node->nested; node; node = node->next_nested)
301 cgraph_optimize_function (node);
303 timevar_pop (TV_INTEGRATION);
306 /* Expand function specified by NODE. */
309 cgraph_expand_function (struct cgraph_node *node)
311 tree decl = node->decl;
312 struct cgraph_edge *e;
314 announce_function (decl);
316 cgraph_optimize_function (node);
318 /* Generate RTL for the body of DECL. Nested functions are expanded
319 via lang_expand_decl_stmt. */
320 (*lang_hooks.callgraph.expand_function) (decl);
322 for (e = node->callers; e; e = e->next_caller)
326 DECL_SAVED_TREE (decl) = NULL;
327 current_function_decl = NULL;
330 /* Fill array order with all nodes with output flag set in the reverse
331 topological order. */
333 cgraph_postorder (struct cgraph_node **order)
335 struct cgraph_node *node, *node2;
338 struct cgraph_edge *edge, last;
340 struct cgraph_node **stack =
341 xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
343 /* We have to deal with cycles nicely, so use a depth first traversal
344 output algorithm. Ignore the fact that some functions won't need
345 to be output and put them into order as well, so we get dependencies
346 right through intline functions. */
347 for (node = cgraph_nodes; node; node = node->next)
349 for (node = cgraph_nodes; node; node = node->next)
356 node->aux = node->callers;
359 while (node2->aux != &last)
362 if (edge->next_caller)
363 node2->aux = edge->next_caller;
366 if (!edge->caller->aux)
368 if (!edge->caller->callers)
369 edge->caller->aux = &last;
371 edge->caller->aux = edge->caller->callers;
372 stack[stack_size++] = node2;
373 node2 = edge->caller;
377 if (node2->aux == &last)
379 order[order_pos++] = node2;
381 node2 = stack[--stack_size];
391 #define INLINED_TIMES(node) ((size_t)(node)->aux)
392 #define SET_INLINED_TIMES(node,times) ((node)->aux = (void *)(times))
394 /* Return list of nodes we decided to inline NODE into, set their output
395 flag and compute INLINED_TIMES.
397 We do simple backtracing to get INLINED_TIMES right. This should not be
398 expensive as we limit the amount of inlining. Alternatively we may first
399 discover set of nodes, topologically sort these and propagate
403 cgraph_inlined_into (struct cgraph_node *node, struct cgraph_node **array)
406 struct cgraph_edge **stack;
407 struct cgraph_edge *e, *e1;
411 /* Fast path: since we traverse in mostly topological order, we will likely
413 for (e = node->callers; e; e = e->next_caller)
420 /* Allocate stack for back-tracking up callgraph. */
421 stack = xmalloc ((cgraph_n_nodes + 1) * sizeof (struct cgraph_edge));
424 /* Push the first edge on to the stack. */
429 struct cgraph_node *caller;
431 /* Look at the edge on the top of the stack. */
435 /* Check if the caller destination has been visited yet. */
438 array[nfound++] = e->caller;
439 /* Mark that we have visited the destination. */
440 caller->output = true;
441 SET_INLINED_TIMES (caller, 0);
443 SET_INLINED_TIMES (caller, INLINED_TIMES (caller) + 1);
445 for (e1 = caller->callers; e1; e1 = e1->next_caller)
454 for (e1 = e->next_caller; e1; e1 = e1->next_caller)
477 if (cgraph_dump_file)
479 fprintf (cgraph_dump_file, "Found inline predecesors of %s:",
480 cgraph_node_name (node));
481 for (i = 0; i < nfound; i++)
483 fprintf (cgraph_dump_file, " %s", cgraph_node_name (array[i]));
484 if (INLINED_TIMES (array[i]) != 1)
485 fprintf (cgraph_dump_file, " (%i times)",
486 (int)INLINED_TIMES (array[i]));
488 fprintf (cgraph_dump_file, "\n");
494 /* Return list of nodes we decided to inline into NODE, set their output
495 flag and compute INLINED_TIMES.
497 This function is identical to cgraph_inlined_into with callers and callees
501 cgraph_inlined_callees (struct cgraph_node *node, struct cgraph_node **array)
504 struct cgraph_edge **stack;
505 struct cgraph_edge *e, *e1;
509 /* Fast path: since we traverse in mostly topological order, we will likely
511 for (e = node->callees; e; e = e->next_callee)
518 /* Allocate stack for back-tracking up callgraph. */
519 stack = xmalloc ((cgraph_n_nodes + 1) * sizeof (struct cgraph_edge));
522 /* Push the first edge on to the stack. */
527 struct cgraph_node *callee;
529 /* Look at the edge on the top of the stack. */
533 /* Check if the callee destination has been visited yet. */
536 array[nfound++] = e->callee;
537 /* Mark that we have visited the destination. */
538 callee->output = true;
539 SET_INLINED_TIMES (callee, 0);
541 SET_INLINED_TIMES (callee, INLINED_TIMES (callee) + 1);
543 for (e1 = callee->callees; e1; e1 = e1->next_callee)
552 for (e1 = e->next_callee; e1; e1 = e1->next_callee)
574 if (cgraph_dump_file)
576 fprintf (cgraph_dump_file, "Found inline successors of %s:",
577 cgraph_node_name (node));
578 for (i = 0; i < nfound; i++)
580 fprintf (cgraph_dump_file, " %s", cgraph_node_name (array[i]));
581 if (INLINED_TIMES (array[i]) != 1)
582 fprintf (cgraph_dump_file, " (%i times)",
583 (int)INLINED_TIMES (array[i]));
585 fprintf (cgraph_dump_file, "\n");
591 /* Estimate size of the function after inlining WHAT into TO. */
594 cgraph_estimate_size_after_inlining (int times, struct cgraph_node *to,
595 struct cgraph_node *what)
597 return (what->global.insns - INSNS_PER_CALL) *times + to->global.insns;
600 /* Estimate the growth caused by inlining NODE into all callees. */
603 cgraph_estimate_growth (struct cgraph_node *node)
607 int clones_added = 0;
608 struct cgraph_edge *e;
610 for (e = node->callers; e; e = e->next_caller)
613 growth += ((cgraph_estimate_size_after_inlining (1, e->caller, node)
615 e->caller->global.insns) *e->caller->global.cloned_times);
616 calls_saved += e->caller->global.cloned_times;
617 clones_added += e->caller->global.cloned_times;
620 /* ??? Wrong for self recursive functions or cases where we decide to not
621 inline for different reasons, but it is not big deal as in that case
622 we will keep the body around, but we will also avoid some inlining. */
623 if (!node->needed && !node->origin && !DECL_EXTERNAL (node->decl))
624 growth -= node->global.insns, clones_added--;
632 /* Update insn sizes after inlining WHAT into TO that is already inlined into
633 all nodes in INLINED array. */
636 cgraph_mark_inline (struct cgraph_node *to, struct cgraph_node *what,
637 struct cgraph_node **inlined, int ninlined,
638 struct cgraph_node **inlined_callees,
639 int ninlined_callees)
644 struct cgraph_edge *e;
648 for (e = what->callers; e; e = e->next_caller)
654 e->inline_call = true;
656 clones += e->caller->global.cloned_times;
658 else if (!e->inline_call)
663 ncalls_inlined += times;
665 new_insns = cgraph_estimate_size_after_inlining (times, to, what);
666 if (to->global.will_be_output)
667 overall_insns += new_insns - to->global.insns;
668 to->global.insns = new_insns;
670 if (!called && !what->needed && !what->origin
671 && !DECL_EXTERNAL (what->decl))
673 if (!what->global.will_be_output)
676 nfunctions_inlined++;
677 what->global.will_be_output = 0;
678 overall_insns -= what->global.insns;
680 what->global.cloned_times += clones;
681 for (i = 0; i < ninlined; i++)
684 cgraph_estimate_size_after_inlining (INLINED_TIMES (inlined[i]) *
685 times, inlined[i], what);
686 if (inlined[i]->global.will_be_output)
687 overall_insns += new_insns - inlined[i]->global.insns;
688 inlined[i]->global.insns = new_insns;
690 for (i = 0; i < ninlined_callees; i++)
692 inlined_callees[i]->global.cloned_times +=
693 INLINED_TIMES (inlined_callees[i]) * clones;
697 /* Return false when inlining WHAT into TO is not good idea as it would cause
698 too large growth of function bodies. */
701 cgraph_check_inline_limits (struct cgraph_node *to, struct cgraph_node *what,
702 struct cgraph_node **inlined, int ninlined)
706 struct cgraph_edge *e;
710 for (e = to->callees; e; e = e->next_callee)
711 if (e->callee == what)
714 /* When inlining large function body called once into small function,
715 take the inlined function as base for limiting the growth. */
716 if (to->local.self_insns > what->local.self_insns)
717 limit = to->local.self_insns;
719 limit = what->local.self_insns;
721 limit += limit * PARAM_VALUE (PARAM_LARGE_FUNCTION_GROWTH) / 100;
723 newsize = cgraph_estimate_size_after_inlining (times, to, what);
724 if (newsize > PARAM_VALUE (PARAM_LARGE_FUNCTION_INSNS)
727 for (i = 0; i < ninlined; i++)
730 cgraph_estimate_size_after_inlining (INLINED_TIMES (inlined[i]) *
731 times, inlined[i], what);
732 if (newsize > PARAM_VALUE (PARAM_LARGE_FUNCTION_INSNS)
734 inlined[i]->local.self_insns *
735 (100 + PARAM_VALUE (PARAM_LARGE_FUNCTION_GROWTH)) / 100)
741 /* Return true when function N is small enought to be inlined. */
744 cgraph_default_inline_p (struct cgraph_node *n)
746 if (!DECL_INLINE (n->decl) || !DECL_SAVED_TREE (n->decl))
748 if (DECL_DECLARED_INLINE_P (n->decl))
749 return n->global.insns < MAX_INLINE_INSNS_SINGLE;
751 return n->global.insns < MAX_INLINE_INSNS_AUTO;
754 /* We use greedy algorithm for inlining of small functions:
755 All inline candidates are put into prioritized heap based on estimated
756 growth of the overall number of instructions and then update the estimates.
758 INLINED and INLINED_CALEES are just pointers to arrays large enought
759 to be passed to cgraph_inlined_into and cgraph_inlined_callees. */
762 cgraph_decide_inlining_of_small_functions (struct cgraph_node **inlined,
763 struct cgraph_node **inlined_callees)
766 struct cgraph_node *node;
767 fibheap_t heap = fibheap_new ();
768 struct fibnode **heap_node =
769 xcalloc (cgraph_max_uid, sizeof (struct fibnode *));
770 int ninlined, ninlined_callees;
771 int max_insns = ((HOST_WIDEST_INT) initial_insns
772 * (100 + PARAM_VALUE (PARAM_INLINE_UNIT_GROWTH)) / 100);
774 /* Put all inline candidates into the heap. */
776 for (node = cgraph_nodes; node; node = node->next)
778 struct cgraph_edge *e;
780 if (!node->local.inlinable || !node->callers
781 || !cgraph_default_inline_p (node))
784 /* Rule out always_inline functions we dealt with earlier. */
785 for (e = node->callers; e; e = e->next_caller)
790 heap_node[node->uid] =
791 fibheap_insert (heap, cgraph_estimate_growth (node), node);
794 if (cgraph_dump_file)
795 fprintf (cgraph_dump_file, "\n\nDeciding on inlining: ");
796 while ((node = fibheap_extract_min (heap)) && overall_insns <= max_insns)
798 struct cgraph_edge *e;
799 int old_insns = overall_insns;
801 heap_node[node->uid] = NULL;
802 if (cgraph_dump_file)
803 fprintf (cgraph_dump_file, "Considering %s %i insns, growth %i.\n",
804 cgraph_node_name (node), node->global.insns,
805 cgraph_estimate_growth (node));
806 if (!cgraph_default_inline_p (node))
808 if (cgraph_dump_file)
809 fprintf (cgraph_dump_file, "Function too large.\n");
812 ninlined_callees = cgraph_inlined_callees (node, inlined_callees);
813 for (e = node->callers; e; e = e->next_caller)
814 if (!e->inline_call && e->caller != node)
816 ninlined = cgraph_inlined_into (e->caller, inlined);
817 if (e->callee->output
818 || !cgraph_check_inline_limits (e->caller, node, inlined,
821 for (i = 0; i < ninlined; i++)
822 inlined[i]->output = 0, node->aux = 0;
823 if (cgraph_dump_file)
824 fprintf (cgraph_dump_file, "Not inlining into %s\n",
825 cgraph_node_name (e->caller));
828 cgraph_mark_inline (e->caller, node, inlined, ninlined,
829 inlined_callees, ninlined_callees);
830 if (heap_node[e->caller->uid])
831 fibheap_replace_key (heap, heap_node[e->caller->uid],
832 cgraph_estimate_growth (e->caller));
834 /* Size of the functions we updated into has changed, so update
836 for (i = 0; i < ninlined; i++)
838 inlined[i]->output = 0, node->aux = 0;
839 if (heap_node[inlined[i]->uid])
840 fibheap_replace_key (heap, heap_node[inlined[i]->uid],
841 cgraph_estimate_growth (inlined[i]));
845 /* Similarly all functions called by function we just inlined
846 are now called more times; update keys. */
848 for (e = node->callees; e; e = e->next_callee)
849 if (!e->inline_call && heap_node[e->callee->uid])
850 fibheap_replace_key (heap, heap_node[e->callee->uid],
851 cgraph_estimate_growth (e->callee));
853 for (i = 0; i < ninlined_callees; i++)
855 struct cgraph_edge *e;
857 for (e = inlined_callees[i]->callees; e; e = e->next_callee)
858 if (!e->inline_call && heap_node[e->callee->uid])
859 fibheap_replace_key (heap, heap_node[e->callee->uid],
860 cgraph_estimate_growth (e->callee));
862 inlined_callees[i]->output = 0, node->aux = 0;
864 if (cgraph_dump_file)
865 fprintf (cgraph_dump_file,
866 "Created %i clones, Num insns:%i (%+i), %.2f%%.\n\n",
867 node->global.cloned_times - 1,
868 overall_insns, overall_insns - old_insns,
869 overall_insns * 100.0 / initial_insns);
871 if (cgraph_dump_file && !fibheap_empty (heap))
872 fprintf (cgraph_dump_file, "inline-unit-growth limit reached.\n");
873 fibheap_delete (heap);
877 /* Decide on the inlining. We do so in the topological order to avoid
878 expenses on updating datastructures. */
881 cgraph_decide_inlining (void)
883 struct cgraph_node *node;
885 struct cgraph_node **order =
886 xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
887 struct cgraph_node **inlined =
888 xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
889 struct cgraph_node **inlined_callees =
890 xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
892 int ninlined_callees;
895 for (node = cgraph_nodes; node; node = node->next)
896 initial_insns += node->local.self_insns;
897 overall_insns = initial_insns;
899 nnodes = cgraph_postorder (order);
901 for (node = cgraph_nodes; node; node = node->next)
904 if (cgraph_dump_file)
905 fprintf (cgraph_dump_file, "\n\nDeciding on always_inline functions:\n");
907 /* In the first pass mark all always_inline edges. Do this with a priority
908 so no our decisions makes this impossible. */
909 for (i = nnodes - 1; i >= 0; i--)
911 struct cgraph_edge *e;
915 for (e = node->callees; e; e = e->next_callee)
916 if (e->callee->local.disregard_inline_limits)
920 if (cgraph_dump_file)
921 fprintf (cgraph_dump_file,
922 "Considering %s %i insns (always inline)\n",
923 cgraph_node_name (node), node->global.insns);
924 ninlined = cgraph_inlined_into (order[i], inlined);
925 for (; e; e = e->next_callee)
927 if (e->inline_call || !e->callee->local.disregard_inline_limits)
929 if (e->callee->output || e->callee == node)
932 cgraph_inlined_callees (e->callee, inlined_callees);
933 cgraph_mark_inline (node, e->callee, inlined, ninlined,
934 inlined_callees, ninlined_callees);
935 for (y = 0; y < ninlined_callees; y++)
936 inlined_callees[y]->output = 0, node->aux = 0;
937 if (cgraph_dump_file)
938 fprintf (cgraph_dump_file, "Inlined %i times. Now %i insns\n\n",
939 node->global.cloned_times, overall_insns);
941 for (y = 0; y < ninlined; y++)
942 inlined[y]->output = 0, node->aux = 0;
945 cgraph_decide_inlining_of_small_functions (inlined, inlined_callees);
947 if (cgraph_dump_file)
948 fprintf (cgraph_dump_file, "\n\nFunctions to inline once:\n");
950 /* And finally decide what functions are called once. */
952 for (i = nnodes - 1; i >= 0; i--)
956 if (node->callers && !node->callers->next_caller && !node->needed
957 && node->local.inlinable && !node->callers->inline_call
958 && !DECL_EXTERNAL (node->decl) && !DECL_COMDAT (node->decl))
961 struct cgraph_node *node1;
963 /* Verify that we won't duplicate the caller. */
964 for (node1 = node->callers->caller;
965 node1->callers && node1->callers->inline_call
966 && ok; node1 = node1->callers->caller)
967 if (node1->callers->next_caller || node1->needed)
971 if (cgraph_dump_file)
972 fprintf (cgraph_dump_file,
973 "Considering %s %i insns (called once)\n",
974 cgraph_node_name (node), node->global.insns);
975 ninlined = cgraph_inlined_into (node->callers->caller, inlined);
976 if (cgraph_check_inline_limits
977 (node->callers->caller, node, inlined, ninlined))
980 cgraph_inlined_callees (node, inlined_callees);
981 cgraph_mark_inline (node->callers->caller, node, inlined,
982 ninlined, inlined_callees,
984 for (y = 0; y < ninlined_callees; y++)
985 inlined_callees[y]->output = 0, node->aux = 0;
986 if (cgraph_dump_file)
987 fprintf (cgraph_dump_file, "Inlined. Now %i insns\n\n", overall_insns);
989 for (y = 0; y < ninlined; y++)
990 inlined[y]->output = 0, node->aux = 0;
995 if (cgraph_dump_file)
996 fprintf (cgraph_dump_file,
997 "\nInlined %i calls, elliminated %i functions, %i insns turned to %i insns.\n",
998 ncalls_inlined, nfunctions_inlined, initial_insns,
1002 free (inlined_callees);
1005 /* Return true when CALLER_DECL should be inlined into CALLEE_DECL. */
1008 cgraph_inline_p (tree caller_decl, tree callee_decl)
1010 struct cgraph_node *caller = cgraph_node (caller_decl);
1011 struct cgraph_node *callee = cgraph_node (callee_decl);
1012 struct cgraph_edge *e;
1014 for (e = caller->callees; e; e = e->next_callee)
1015 if (e->callee == callee)
1016 return e->inline_call;
1017 /* We do not record builtins in the callgraph. Perhaps it would make more
1018 sense to do so and then prune out those not overwritten by explicit
1022 /* Expand all functions that must be output.
1024 Attempt to topologically sort the nodes so function is output when
1025 all called functions are already assembled to allow data to be
1026 propagated across the callgraph. Use a stack to get smaller distance
1027 between a function and it's callees (later we may choose to use a more
1028 sophisticated algorithm for function reordering; we will likely want
1029 to use subsections to make the output functions appear in top-down
1033 cgraph_expand_functions (void)
1035 struct cgraph_node *node;
1036 struct cgraph_node **order =
1037 xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
1041 cgraph_mark_functions_to_output ();
1043 order_pos = cgraph_postorder (order);
1045 for (i = order_pos - 1; i >= 0; i--)
1050 if (!node->reachable)
1053 cgraph_expand_function (node);
1059 /* Mark all local functions.
1061 A local function is one whose calls can occur only in the
1062 current compilation unit, so we change its calling convention.
1063 We simply mark all static functions whose address is not taken
1067 cgraph_mark_local_functions (void)
1069 struct cgraph_node *node;
1071 if (cgraph_dump_file)
1072 fprintf (cgraph_dump_file, "Marking local functions:");
1074 /* Figure out functions we want to assemble. */
1075 for (node = cgraph_nodes; node; node = node->next)
1077 node->local.local = (!node->needed
1078 && DECL_SAVED_TREE (node->decl)
1079 && !TREE_PUBLIC (node->decl));
1080 if (cgraph_dump_file && node->local.local)
1081 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
1083 if (cgraph_dump_file)
1084 fprintf (cgraph_dump_file, "\n");
1087 /* Perform simple optimizations based on callgraph. */
1090 cgraph_optimize (void)
1092 timevar_push (TV_CGRAPHOPT);
1094 fprintf (stderr, "Performing intraprocedural optimizations\n");
1095 if (cgraph_dump_file)
1097 fprintf (cgraph_dump_file, "Initial callgraph:");
1098 dump_cgraph (cgraph_dump_file);
1100 cgraph_mark_local_functions ();
1102 cgraph_decide_inlining ();
1104 cgraph_global_info_ready = true;
1105 if (cgraph_dump_file)
1107 fprintf (cgraph_dump_file, "Optimized callgraph:");
1108 dump_cgraph (cgraph_dump_file);
1110 timevar_pop (TV_CGRAPHOPT);
1112 fprintf (stderr, "Assembling functions:");
1114 /* Output everything. */
1115 cgraph_expand_functions ();
1116 if (cgraph_dump_file)
1118 fprintf (cgraph_dump_file, "Final callgraph:");
1119 dump_cgraph (cgraph_dump_file);