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 if (/* Externally visible functions must be output. The exception are
69 COMDAT functions that must be output only when they are needed.
70 Similarly are handled deferred functions and
71 external functions (GCC extension "extern inline") */
72 (TREE_PUBLIC (decl
) && !DECL_COMDAT (decl
) && !DECL_EXTERNAL (decl
))
73 /* ??? Constructors and destructors not called otherwise can be inlined
74 into single construction/destruction function per section to save some
75 resources. For now just mark it as reachable. */
76 || DECL_STATIC_CONSTRUCTOR (decl
)
77 || DECL_STATIC_DESTRUCTOR (decl
)
78 /* Function whose name is output to the assembler file must be produced.
79 It is possible to assemble the name later after finalizing the function
80 and the fact is noticed in assemble_name then. */
81 || (DECL_ASSEMBLER_NAME_SET_P (decl
)
82 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl
)))
83 || lookup_attribute ("used", DECL_ATTRIBUTES (decl
)))
85 cgraph_mark_needed_node (node
, 1);
88 (*debug_hooks
->deferred_inline_function
) (decl
);
91 /* Walk tree and record all calls. Called via walk_tree. */
93 record_call_1 (tree
*tp
, int *walk_subtrees
, void *data
)
95 if (TREE_CODE (*tp
) == VAR_DECL
&& TREE_STATIC (*tp
))
96 cgraph_varpool_mark_needed_node (cgraph_varpool_node (*tp
));
97 /* Record dereferences to the functions. This makes the functions
98 reachable unconditionally. */
99 else if (TREE_CODE (*tp
) == ADDR_EXPR
)
101 tree decl
= TREE_OPERAND (*tp
, 0);
102 if (TREE_CODE (decl
) == FUNCTION_DECL
)
103 cgraph_mark_needed_node (cgraph_node (decl
), 1);
105 else if (TREE_CODE (*tp
) == CALL_EXPR
)
107 tree decl
= get_callee_fndecl (*tp
);
108 if (decl
&& TREE_CODE (decl
) == FUNCTION_DECL
)
110 if (DECL_BUILT_IN (decl
))
112 cgraph_record_call (data
, decl
);
114 /* When we see a function call, we don't want to look at the
115 function reference in the ADDR_EXPR that is hanging from
116 the CALL_EXPR we're examining here, because we would
117 conclude incorrectly that the function's address could be
118 taken by something that is not a function call. So only
119 walk the function parameter list, skip the other subtrees. */
121 walk_tree (&TREE_OPERAND (*tp
, 1), record_call_1
, data
, NULL
);
128 /* Create cgraph edges for function calls inside BODY from DECL. */
131 cgraph_create_edges (tree decl
, tree body
)
133 /* The nodes we're interested in are never shared, so walk
134 the tree ignoring duplicates. */
135 walk_tree_without_duplicates (&body
, record_call_1
, decl
);
138 /* Analyze the whole compilation unit once it is parsed completely. */
141 cgraph_finalize_compilation_unit (void)
143 struct cgraph_node
*node
;
144 struct cgraph_edge
*edge
;
146 cgraph_varpool_assemble_pending_decls ();
148 fprintf (stderr
, "\nAnalyzing compilation unit\n");
150 timevar_push (TV_CGRAPH
);
151 if (cgraph_dump_file
)
153 fprintf (cgraph_dump_file
, "\nInitial entry points:");
154 for (node
= cgraph_nodes
; node
; node
= node
->next
)
155 if (node
->needed
&& DECL_SAVED_TREE (node
->decl
))
156 fprintf (cgraph_dump_file
, " %s", cgraph_node_name (node
));
157 fprintf (cgraph_dump_file
, "\n");
160 /* Propagate reachability flag and lower representation of all reachable
161 functions. In the future, lowering will introduce new functions and
162 new entry points on the way (by template instantiation and virtual
163 method table generation for instance). */
164 while (cgraph_nodes_queue
)
166 tree decl
= cgraph_nodes_queue
->decl
;
168 node
= cgraph_nodes_queue
;
169 cgraph_nodes_queue
= cgraph_nodes_queue
->next_needed
;
171 if (node
->lowered
|| !node
->reachable
|| !DECL_SAVED_TREE (decl
))
174 if (lang_hooks
.callgraph
.lower_function
)
175 (*lang_hooks
.callgraph
.lower_function
) (decl
);
177 current_function_decl
= node
->decl
;
179 /* At the moment frontend automatically emits all nested functions. */
182 struct cgraph_node
*node2
;
184 for (node2
= node
->nested
; node2
; node2
= node2
->next_nested
)
185 if (!node2
->reachable
)
186 cgraph_mark_needed_node (node2
, 0);
189 /* First kill forward declaration so reverse inlining works properly. */
190 cgraph_create_edges (decl
, DECL_SAVED_TREE (decl
));
192 node
->local
.inlinable
= tree_inlinable_function_p (decl
, 1);
193 if (!DECL_ESTIMATED_INSNS (decl
))
194 DECL_ESTIMATED_INSNS (decl
)
195 = (*lang_hooks
.tree_inlining
.estimate_num_insns
) (decl
);
196 node
->local
.self_insns
= DECL_ESTIMATED_INSNS (decl
);
197 if (node
->local
.inlinable
)
198 node
->local
.disgread_inline_limits
199 = (*lang_hooks
.tree_inlining
.disregard_inline_limits
) (decl
);
201 for (edge
= node
->callees
; edge
; edge
= edge
->next_callee
)
203 if (!edge
->callee
->reachable
)
204 cgraph_mark_needed_node (edge
->callee
, 0);
206 node
->lowered
= true;
207 cgraph_varpool_assemble_pending_decls ();
209 /* Collect entry points to the unit. */
211 if (cgraph_dump_file
)
213 fprintf (cgraph_dump_file
, "\nUnit entry points:");
214 for (node
= cgraph_nodes
; node
; node
= node
->next
)
215 if (node
->needed
&& DECL_SAVED_TREE (node
->decl
))
216 fprintf (cgraph_dump_file
, " %s", cgraph_node_name (node
));
217 fprintf (cgraph_dump_file
, "\n");
220 if (cgraph_dump_file
)
221 fprintf (cgraph_dump_file
, "\nReclaiming functions:");
223 for (node
= cgraph_nodes
; node
; node
= node
->next
)
225 tree decl
= node
->decl
;
227 if (!node
->reachable
&& DECL_SAVED_TREE (decl
))
229 cgraph_remove_node (node
);
230 if (cgraph_dump_file
)
231 fprintf (cgraph_dump_file
, " %s", cgraph_node_name (node
));
234 if (cgraph_dump_file
)
235 fprintf (cgraph_dump_file
, "\n");
237 timevar_pop (TV_CGRAPH
);
240 /* Figure out what functions we want to assemble. */
243 cgraph_mark_functions_to_output (void)
245 struct cgraph_node
*node
;
247 for (node
= cgraph_nodes
; node
; node
= node
->next
)
249 tree decl
= node
->decl
;
250 struct cgraph_edge
*e
;
254 for (e
= node
->callers
; e
; e
= e
->next_caller
)
258 /* We need to output all local functions that are used and not
259 always inlined, as well as those that are reachable from
260 outside the current compilation unit. */
261 if (DECL_SAVED_TREE (decl
)
263 || (e
&& node
->reachable
))
264 && !TREE_ASM_WRITTEN (decl
) && !node
->origin
265 && !DECL_EXTERNAL (decl
))
270 /* Optimize the function before expansion. */
273 cgraph_optimize_function (struct cgraph_node
*node
)
275 tree decl
= node
->decl
;
277 timevar_push (TV_INTEGRATION
);
278 /* optimize_inline_calls avoids inlining of current_function_decl. */
279 current_function_decl
= 0;
280 if (flag_inline_trees
)
281 optimize_inline_calls (decl
);
284 for (node
= node
->nested
; node
; node
= node
->next_nested
)
285 cgraph_optimize_function (node
);
287 timevar_pop (TV_INTEGRATION
);
290 /* Expand function specified by NODE. */
293 cgraph_expand_function (struct cgraph_node
*node
)
295 tree decl
= node
->decl
;
296 struct cgraph_edge
*e
;
298 announce_function (decl
);
300 cgraph_optimize_function (node
);
302 /* Generate RTL for the body of DECL. Nested functions are expanded
303 via lang_expand_decl_stmt. */
304 (*lang_hooks
.callgraph
.expand_function
) (decl
);
306 for (e
= node
->callers
; e
; e
= e
->next_caller
)
310 DECL_SAVED_TREE (decl
) = NULL
;
311 current_function_decl
= NULL
;
314 /* Fill array order with all nodes with output flag set in the reverse
315 topological order. */
317 cgraph_postorder (struct cgraph_node
**order
)
319 struct cgraph_node
*node
, *node2
;
322 struct cgraph_edge
*edge
, last
;
324 struct cgraph_node
**stack
=
325 xcalloc (sizeof (struct cgraph_node
*), cgraph_n_nodes
);
327 /* We have to deal with cycles nicely, so use a depth first traversal
328 output algorithm. Ignore the fact that some functions won't need
329 to be output and put them into order as well, so we get dependencies
330 right through intline functions. */
331 for (node
= cgraph_nodes
; node
; node
= node
->next
)
333 for (node
= cgraph_nodes
; node
; node
= node
->next
)
340 node
->aux
= node
->callers
;
343 while (node2
->aux
!= &last
)
346 if (edge
->next_caller
)
347 node2
->aux
= edge
->next_caller
;
350 if (!edge
->caller
->aux
)
352 if (!edge
->caller
->callers
)
353 edge
->caller
->aux
= &last
;
355 edge
->caller
->aux
= edge
->caller
->callers
;
356 stack
[stack_size
++] = node2
;
357 node2
= edge
->caller
;
361 if (node2
->aux
== &last
)
363 order
[order_pos
++] = node2
;
365 node2
= stack
[--stack_size
];
375 #define INLINED_TIMES(node) ((size_t)(node)->aux)
376 #define SET_INLINED_TIMES(node,times) ((node)->aux = (void *)(times))
378 /* Return list of nodes we decided to inline NODE into, set their output
379 flag and compute INLINED_TIMES.
381 We do simple backtracing to get INLINED_TIMES right. This should not be
382 expensive as we limit the amount of inlining. Alternatively we may first
383 discover set of nodes, topologically sort these and propagate
387 cgraph_inlined_into (struct cgraph_node
*node
, struct cgraph_node
**array
)
390 struct cgraph_edge
**stack
;
391 struct cgraph_edge
*e
, *e1
;
395 /* Fast path: since we traverse in mostly topological order, we will likely
397 for (e
= node
->callers
; e
; e
= e
->next_caller
)
404 /* Allocate stack for back-tracking up callgraph. */
405 stack
= xmalloc ((cgraph_n_nodes
+ 1) * sizeof (struct cgraph_edge
));
408 /* Push the first edge on to the stack. */
413 struct cgraph_node
*caller
;
415 /* Look at the edge on the top of the stack. */
419 /* Check if the caller destination has been visited yet. */
422 array
[nfound
++] = e
->caller
;
423 /* Mark that we have visited the destination. */
424 caller
->output
= true;
425 SET_INLINED_TIMES (caller
, 0);
427 SET_INLINED_TIMES (caller
, INLINED_TIMES (caller
) + 1);
429 for (e1
= caller
->callers
; e1
; e1
= e1
->next_caller
)
438 for (e1
= e
->next_caller
; e1
; e1
= e1
->next_caller
)
461 if (cgraph_dump_file
)
463 fprintf (cgraph_dump_file
, "Found inline predecesors of %s:",
464 cgraph_node_name (node
));
465 for (i
= 0; i
< nfound
; i
++)
467 fprintf (cgraph_dump_file
, " %s", cgraph_node_name (array
[i
]));
468 if (INLINED_TIMES (array
[i
]) != 1)
469 fprintf (cgraph_dump_file
, " (%i times)",
470 (int)INLINED_TIMES (array
[i
]));
472 fprintf (cgraph_dump_file
, "\n");
478 /* Return list of nodes we decided to inline into NODE, set their output
479 flag and compute INLINED_TIMES.
481 This function is identical to cgraph_inlined_into with callers and callees
485 cgraph_inlined_callees (struct cgraph_node
*node
, struct cgraph_node
**array
)
488 struct cgraph_edge
**stack
;
489 struct cgraph_edge
*e
, *e1
;
493 /* Fast path: since we traverse in mostly topological order, we will likely
495 for (e
= node
->callees
; e
; e
= e
->next_callee
)
502 /* Allocate stack for back-tracking up callgraph. */
503 stack
= xmalloc ((cgraph_n_nodes
+ 1) * sizeof (struct cgraph_edge
));
506 /* Push the first edge on to the stack. */
511 struct cgraph_node
*callee
;
513 /* Look at the edge on the top of the stack. */
517 /* Check if the callee destination has been visited yet. */
520 array
[nfound
++] = e
->callee
;
521 /* Mark that we have visited the destination. */
522 callee
->output
= true;
523 SET_INLINED_TIMES (callee
, 0);
525 SET_INLINED_TIMES (callee
, INLINED_TIMES (callee
) + 1);
527 for (e1
= callee
->callees
; e1
; e1
= e1
->next_callee
)
536 for (e1
= e
->next_callee
; e1
; e1
= e1
->next_callee
)
558 if (cgraph_dump_file
)
560 fprintf (cgraph_dump_file
, "Found inline successors of %s:",
561 cgraph_node_name (node
));
562 for (i
= 0; i
< nfound
; i
++)
564 fprintf (cgraph_dump_file
, " %s", cgraph_node_name (array
[i
]));
565 if (INLINED_TIMES (array
[i
]) != 1)
566 fprintf (cgraph_dump_file
, " (%i times)",
567 (int)INLINED_TIMES (array
[i
]));
569 fprintf (cgraph_dump_file
, "\n");
575 /* Estimate size of the function after inlining WHAT into TO. */
578 cgraph_estimate_size_after_inlining (int times
, struct cgraph_node
*to
,
579 struct cgraph_node
*what
)
581 return (what
->global
.insns
- INSNS_PER_CALL
) *times
+ to
->global
.insns
;
584 /* Estimate the growth caused by inlining NODE into all callees. */
587 cgraph_estimate_growth (struct cgraph_node
*node
)
591 int clones_added
= 0;
592 struct cgraph_edge
*e
;
594 for (e
= node
->callers
; e
; e
= e
->next_caller
)
597 growth
+= ((cgraph_estimate_size_after_inlining (1, e
->caller
, node
)
599 e
->caller
->global
.insns
) *e
->caller
->global
.cloned_times
);
600 calls_saved
+= e
->caller
->global
.cloned_times
;
601 clones_added
+= e
->caller
->global
.cloned_times
;
604 /* ??? Wrong for self recursive functions or cases where we decide to not
605 inline for different reasons, but it is not big deal as in that case
606 we will keep the body around, but we will also avoid some inlining. */
607 if (!node
->needed
&& !node
->origin
&& !DECL_EXTERNAL (node
->decl
))
608 growth
-= node
->global
.insns
, clones_added
--;
616 /* Update insn sizes after inlining WHAT into TO that is already inlined into
617 all nodes in INLINED array. */
620 cgraph_mark_inline (struct cgraph_node
*to
, struct cgraph_node
*what
,
621 struct cgraph_node
**inlined
, int ninlined
,
622 struct cgraph_node
**inlined_callees
,
623 int ninlined_callees
)
628 struct cgraph_edge
*e
;
632 for (e
= what
->callers
; e
; e
= e
->next_caller
)
638 e
->inline_call
= true;
640 clones
+= e
->caller
->global
.cloned_times
;
642 else if (!e
->inline_call
)
647 ncalls_inlined
+= times
;
649 new_insns
= cgraph_estimate_size_after_inlining (times
, to
, what
);
650 if (to
->global
.will_be_output
)
651 overall_insns
+= new_insns
- to
->global
.insns
;
652 to
->global
.insns
= new_insns
;
654 to
->global
.calls
+= (what
->global
.calls
- 1) *times
;
655 if (!called
&& !what
->needed
&& !what
->origin
656 && !DECL_EXTERNAL (what
->decl
))
658 if (!what
->global
.will_be_output
)
661 nfunctions_inlined
++;
662 what
->global
.will_be_output
= 0;
663 overall_insns
-= what
->global
.insns
;
665 what
->global
.cloned_times
+= clones
;
666 if (to
->global
.calls
< 0)
668 for (i
= 0; i
< ninlined
; i
++)
671 cgraph_estimate_size_after_inlining (INLINED_TIMES (inlined
[i
]) *
672 times
, inlined
[i
], what
);
673 if (inlined
[i
]->global
.will_be_output
)
674 overall_insns
+= new_insns
- inlined
[i
]->global
.insns
;
675 inlined
[i
]->global
.insns
= new_insns
;
676 inlined
[i
]->global
.calls
+=
677 (what
->global
.calls
- 1) *INLINED_TIMES (inlined
[i
]) * times
;
678 if (inlined
[i
]->global
.calls
< 0)
681 for (i
= 0; i
< ninlined_callees
; i
++)
683 inlined_callees
[i
]->global
.cloned_times
+=
684 INLINED_TIMES (inlined_callees
[i
]) * clones
;
688 /* Return false when inlining WHAT into TO is not good idea as it would cause
689 too large growth of function bodies. */
692 cgraph_check_inline_limits (struct cgraph_node
*to
, struct cgraph_node
*what
,
693 struct cgraph_node
**inlined
, int ninlined
)
697 struct cgraph_edge
*e
;
701 for (e
= to
->callees
; e
; e
= e
->next_callee
)
702 if (e
->callee
== what
)
705 /* When inlining large function body called once into small function,
706 take the inlined function as base for limiting the growth. */
707 if (to
->local
.self_insns
> what
->local
.self_insns
)
708 limit
= to
->local
.self_insns
;
710 limit
= what
->local
.self_insns
;
712 limit
+= limit
* PARAM_VALUE (PARAM_LARGE_FUNCTION_GROWTH
) / 100;
714 newsize
= cgraph_estimate_size_after_inlining (times
, to
, what
);
715 if (newsize
> PARAM_VALUE (PARAM_LARGE_FUNCTION_INSNS
)
718 for (i
= 0; i
< ninlined
; i
++)
721 cgraph_estimate_size_after_inlining (INLINED_TIMES (inlined
[i
]) *
722 times
, inlined
[i
], what
);
723 if (newsize
> PARAM_VALUE (PARAM_LARGE_FUNCTION_INSNS
)
725 inlined
[i
]->local
.self_insns
*
726 (100 + PARAM_VALUE (PARAM_LARGE_FUNCTION_GROWTH
)) / 100)
732 /* Return true when function N is small enought to be inlined. */
735 cgraph_default_inline_p (struct cgraph_node
*n
)
737 if (!DECL_INLINE (n
->decl
) || !DECL_SAVED_TREE (n
->decl
))
739 if (DID_INLINE_FUNC (n
->decl
))
740 return n
->global
.insns
< MAX_INLINE_INSNS_AUTO
;
742 return n
->global
.insns
< MAX_INLINE_INSNS_SINGLE
;
745 /* We use greedy algorithm for inlining of small functions:
746 All inline candidates are put into prioritized heap based on estimated
747 growth of the overall number of instructions and then update the estimates.
749 INLINED and INLINED_CALEES are just pointers to arrays large enought
750 to be passed to cgraph_inlined_into and cgraph_inlined_callees. */
753 cgraph_decide_inlining_of_small_functions (struct cgraph_node
**inlined
,
754 struct cgraph_node
**inlined_callees
)
757 struct cgraph_node
*node
;
758 fibheap_t heap
= fibheap_new ();
759 struct fibnode
**heap_node
=
760 xcalloc (sizeof (struct fibnode
*), cgraph_max_uid
);
761 int ninlined
, ninlined_callees
;
762 int max_insns
= ((HOST_WIDEST_INT
) initial_insns
763 * (100 + PARAM_VALUE (PARAM_INLINE_UNIT_GROWTH
)) / 100);
765 /* Put all inline candidates into the heap. */
767 for (node
= cgraph_nodes
; node
; node
= node
->next
)
769 struct cgraph_edge
*e
;
771 if (!node
->local
.inlinable
|| !node
->callers
772 || !cgraph_default_inline_p (node
))
775 /* Rule out always_inline functions we dealt with earler. */
776 for (e
= node
->callers
; e
; e
= e
->next_caller
)
781 heap_node
[node
->uid
] =
782 fibheap_insert (heap
, cgraph_estimate_growth (node
), node
);
785 if (cgraph_dump_file
)
786 fprintf (cgraph_dump_file
, "\n\nDeciding on inlining: ");
787 while ((node
= fibheap_extract_min (heap
)) && overall_insns
<= max_insns
)
789 struct cgraph_edge
*e
;
790 int old_insns
= overall_insns
;
792 heap_node
[node
->uid
] = NULL
;
793 if (cgraph_dump_file
)
794 fprintf (cgraph_dump_file
, "Considering %s %i insns, growth %i.\n",
795 cgraph_node_name (node
), node
->global
.insns
,
796 cgraph_estimate_growth (node
));
797 if (!cgraph_default_inline_p (node
))
799 if (cgraph_dump_file
)
800 fprintf (cgraph_dump_file
, "Function too large.\n");
803 ninlined_callees
= cgraph_inlined_callees (node
, inlined_callees
);
804 for (e
= node
->callers
; e
; e
= e
->next_caller
)
805 if (!e
->inline_call
&& e
->caller
!= node
)
807 ninlined
= cgraph_inlined_into (e
->caller
, inlined
);
808 if (e
->callee
->output
809 || !cgraph_check_inline_limits (e
->caller
, node
, inlined
,
812 for (i
= 0; i
< ninlined
; i
++)
813 inlined
[i
]->output
= 0, node
->aux
= 0;
814 if (cgraph_dump_file
)
815 fprintf (cgraph_dump_file
, "Not inlining into %s\n",
816 cgraph_node_name (e
->caller
));
819 cgraph_mark_inline (e
->caller
, node
, inlined
, ninlined
,
820 inlined_callees
, ninlined_callees
);
821 if (heap_node
[e
->caller
->uid
])
822 fibheap_replace_key (heap
, heap_node
[e
->caller
->uid
],
823 cgraph_estimate_growth (e
->caller
));
825 /* Size of the functions we updated into has changed, so update
827 for (i
= 0; i
< ninlined
; i
++)
829 inlined
[i
]->output
= 0, node
->aux
= 0;
830 if (heap_node
[inlined
[i
]->uid
])
831 fibheap_replace_key (heap
, heap_node
[inlined
[i
]->uid
],
832 cgraph_estimate_growth (inlined
[i
]));
836 /* Similarly all functions called by function we just inlined
837 are now called more times; update keys. */
839 for (e
= node
->callees
; e
; e
= e
->next_callee
)
840 if (!e
->inline_call
&& heap_node
[e
->callee
->uid
])
841 fibheap_replace_key (heap
, heap_node
[e
->callee
->uid
],
842 cgraph_estimate_growth (e
->callee
));
844 for (i
= 0; i
< ninlined_callees
; i
++)
846 struct cgraph_edge
*e
;
848 for (e
= inlined_callees
[i
]->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 inlined_callees
[i
]->output
= 0, node
->aux
= 0;
855 if (cgraph_dump_file
)
856 fprintf (cgraph_dump_file
,
857 "Created %i clones, Num insns:%i (%+i), %.2f%%.\n\n",
858 node
->global
.cloned_times
- 1,
859 overall_insns
, overall_insns
- old_insns
,
860 overall_insns
* 100.0 / initial_insns
);
862 if (cgraph_dump_file
&& !fibheap_empty (heap
))
863 fprintf (cgraph_dump_file
, "inline-unit-growth limit reached.\n");
864 fibheap_delete (heap
);
868 /* Decide on the inlining. We do so in the topological order to avoid
869 expenses on updating datastructures. */
872 cgraph_decide_inlining (void)
874 struct cgraph_node
*node
;
876 struct cgraph_node
**order
=
877 xcalloc (sizeof (struct cgraph_node
*), cgraph_n_nodes
);
878 struct cgraph_node
**inlined
=
879 xcalloc (sizeof (struct cgraph_node
*), cgraph_n_nodes
);
880 struct cgraph_node
**inlined_callees
=
881 xcalloc (sizeof (struct cgraph_node
*), cgraph_n_nodes
);
883 int ninlined_callees
;
886 for (node
= cgraph_nodes
; node
; node
= node
->next
)
889 struct cgraph_edge
*e
;
891 node
->global
.insns
= node
->local
.self_insns
;
892 for (e
= node
->callees
; e
; e
= e
->next_callee
)
894 node
->global
.calls
= ncalls
;
895 if (!DECL_EXTERNAL (node
->decl
))
897 node
->global
.cloned_times
= 1;
898 initial_insns
+= node
->local
.self_insns
;
899 node
->global
.will_be_output
= true;
902 overall_insns
= initial_insns
;
904 nnodes
= cgraph_postorder (order
);
906 for (node
= cgraph_nodes
; node
; node
= node
->next
)
909 if (cgraph_dump_file
)
910 fprintf (cgraph_dump_file
, "\n\nDeciding on always_inline functions:\n");
912 /* In the first pass mark all always_inline edges. Do this with a priority
913 so no our decisions makes this impossible. */
914 for (i
= nnodes
- 1; i
>= 0; i
--)
916 struct cgraph_edge
*e
;
920 for (e
= node
->callees
; e
; e
= e
->next_callee
)
921 if (e
->callee
->local
.disgread_inline_limits
)
925 if (cgraph_dump_file
)
926 fprintf (cgraph_dump_file
,
927 "Considering %s %i insns (always inline)\n",
928 cgraph_node_name (node
), node
->global
.insns
);
929 ninlined
= cgraph_inlined_into (order
[i
], inlined
);
930 for (; e
; e
= e
->next_callee
)
932 if (e
->inline_call
|| !e
->callee
->local
.disgread_inline_limits
)
934 if (e
->callee
->output
|| e
->callee
== node
)
937 cgraph_inlined_callees (e
->callee
, inlined_callees
);
938 cgraph_mark_inline (node
, e
->callee
, inlined
, ninlined
,
939 inlined_callees
, ninlined_callees
);
940 for (y
= 0; y
< ninlined_callees
; y
++)
941 inlined_callees
[y
]->output
= 0, node
->aux
= 0;
942 if (cgraph_dump_file
)
943 fprintf (cgraph_dump_file
, "Inlined %i times. Now %i insns\n\n",
944 node
->global
.cloned_times
, overall_insns
);
946 for (y
= 0; y
< ninlined
; y
++)
947 inlined
[y
]->output
= 0, node
->aux
= 0;
950 cgraph_decide_inlining_of_small_functions (inlined
, inlined_callees
);
952 if (cgraph_dump_file
)
953 fprintf (cgraph_dump_file
, "\n\nFunctions to inline once:\n");
955 /* And finally decide what functions are called once. */
957 for (i
= nnodes
- 1; i
>= 0; i
--)
961 if (node
->callers
&& !node
->callers
->next_caller
&& !node
->needed
962 && node
->local
.inlinable
&& !node
->callers
->inline_call
963 && !DECL_EXTERNAL (node
->decl
) && !DECL_COMDAT (node
->decl
))
966 struct cgraph_node
*node1
;
968 /* Verify that we won't duplicate the caller. */
969 for (node1
= node
->callers
->caller
;
970 node1
->callers
&& node1
->callers
->inline_call
971 && ok
; node1
= node1
->callers
->caller
)
972 if (node1
->callers
->next_caller
|| node1
->needed
)
976 if (cgraph_dump_file
)
977 fprintf (cgraph_dump_file
,
978 "Considering %s %i insns (called once)\n",
979 cgraph_node_name (node
), node
->global
.insns
);
980 ninlined
= cgraph_inlined_into (node
->callers
->caller
, inlined
);
981 if (cgraph_check_inline_limits
982 (node
->callers
->caller
, node
, inlined
, ninlined
))
985 cgraph_inlined_callees (node
, inlined_callees
);
986 cgraph_mark_inline (node
->callers
->caller
, node
, inlined
,
987 ninlined
, inlined_callees
,
989 for (y
= 0; y
< ninlined_callees
; y
++)
990 inlined_callees
[y
]->output
= 0, node
->aux
= 0;
991 if (cgraph_dump_file
)
992 fprintf (cgraph_dump_file
, "Inlined. Now %i insns\n\n", overall_insns
);
994 for (y
= 0; y
< ninlined
; y
++)
995 inlined
[y
]->output
= 0, node
->aux
= 0;
1000 if (cgraph_dump_file
)
1001 fprintf (cgraph_dump_file
,
1002 "\nInlined %i calls, elliminated %i functions, %i insns turned to %i insns.\n",
1003 ncalls_inlined
, nfunctions_inlined
, initial_insns
,
1007 free (inlined_callees
);
1010 /* Return true when CALLER_DECL should be inlined into CALLEE_DECL. */
1013 cgraph_inline_p (tree caller_decl
, tree callee_decl
)
1015 struct cgraph_node
*caller
= cgraph_node (caller_decl
);
1016 struct cgraph_node
*callee
= cgraph_node (callee_decl
);
1017 struct cgraph_edge
*e
;
1019 for (e
= caller
->callees
; e
; e
= e
->next_callee
)
1020 if (e
->callee
== callee
)
1021 return e
->inline_call
;
1022 /* We do not record builtins in the callgraph. Perhaps it would make more
1023 sense to do so and then prune out those not overwriten by explicit
1027 /* Expand all functions that must be output.
1029 Attempt to topologically sort the nodes so function is output when
1030 all called functions are already assembled to allow data to be
1031 propagated accross the callgraph. Use a stack to get smaller distance
1032 between a function and it's callees (later we may choose to use a more
1033 sophisticated algorithm for function reordering; we will likely want
1034 to use subsections to make the output functions appear in top-down
1038 cgraph_expand_functions (void)
1040 struct cgraph_node
*node
;
1041 struct cgraph_node
**order
=
1042 xcalloc (sizeof (struct cgraph_node
*), cgraph_n_nodes
);
1046 cgraph_mark_functions_to_output ();
1048 order_pos
= cgraph_postorder (order
);
1050 for (i
= order_pos
- 1; i
>= 0; i
--)
1055 if (!node
->reachable
)
1058 cgraph_expand_function (node
);
1064 /* Mark all local functions.
1066 Local function is function whose calls can occur only in the
1067 current compilation unit so we change it's calling convetion.
1068 We simply mark all static functions whose address is not taken
1072 cgraph_mark_local_functions (void)
1074 struct cgraph_node
*node
;
1076 if (cgraph_dump_file
)
1077 fprintf (cgraph_dump_file
, "Marking local functions:");
1079 /* Figure out functions we want to assemble. */
1080 for (node
= cgraph_nodes
; node
; node
= node
->next
)
1082 node
->local
.local
= (!node
->needed
1083 && DECL_SAVED_TREE (node
->decl
)
1084 && !TREE_PUBLIC (node
->decl
));
1085 if (cgraph_dump_file
&& node
->local
.local
)
1086 fprintf (cgraph_dump_file
, " %s", cgraph_node_name (node
));
1088 if (cgraph_dump_file
)
1089 fprintf (cgraph_dump_file
, "\n");
1092 /* Perform simple optimizations based on callgraph. */
1095 cgraph_optimize (void)
1097 timevar_push (TV_CGRAPHOPT
);
1099 fprintf (stderr
, "Performing intraprocedural optimizations\n");
1100 if (cgraph_dump_file
)
1102 fprintf (cgraph_dump_file
, "Initial callgraph:");
1103 dump_cgraph (cgraph_dump_file
);
1105 cgraph_mark_local_functions ();
1107 cgraph_decide_inlining ();
1109 cgraph_global_info_ready
= true;
1110 if (cgraph_dump_file
)
1112 fprintf (cgraph_dump_file
, "Optimized callgraph:");
1113 dump_cgraph (cgraph_dump_file
);
1115 timevar_pop (TV_CGRAPHOPT
);
1117 fprintf (stderr
, "Assembling functions:");
1119 /* Output everything. */
1120 cgraph_expand_functions ();
1121 if (cgraph_dump_file
)
1123 fprintf (cgraph_dump_file
, "Final callgraph:");
1124 dump_cgraph (cgraph_dump_file
);