1e4b17023SJohn Marino /* Callgraph transformations to handle inlining
2e4b17023SJohn Marino Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011
3e4b17023SJohn Marino Free Software Foundation, Inc.
4e4b17023SJohn Marino Contributed by Jan Hubicka
5e4b17023SJohn Marino
6e4b17023SJohn Marino This file is part of GCC.
7e4b17023SJohn Marino
8e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11e4b17023SJohn Marino version.
12e4b17023SJohn Marino
13e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16e4b17023SJohn Marino for more details.
17e4b17023SJohn Marino
18e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
20e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
21e4b17023SJohn Marino
22e4b17023SJohn Marino /* The inline decisions are stored in callgraph in "inline plan" and
23e4b17023SJohn Marino applied later.
24e4b17023SJohn Marino
25e4b17023SJohn Marino To mark given call inline, use inline_call function.
26e4b17023SJohn Marino The function marks the edge inlinable and, if necessary, produces
27e4b17023SJohn Marino virtual clone in the callgraph representing the new copy of callee's
28e4b17023SJohn Marino function body.
29e4b17023SJohn Marino
30e4b17023SJohn Marino The inline plan is applied on given function body by inline_transform. */
31e4b17023SJohn Marino
32e4b17023SJohn Marino #include "config.h"
33e4b17023SJohn Marino #include "system.h"
34e4b17023SJohn Marino #include "coretypes.h"
35e4b17023SJohn Marino #include "tm.h"
36e4b17023SJohn Marino #include "tree.h"
37e4b17023SJohn Marino #include "langhooks.h"
38e4b17023SJohn Marino #include "cgraph.h"
39e4b17023SJohn Marino #include "timevar.h"
40e4b17023SJohn Marino #include "output.h"
41e4b17023SJohn Marino #include "intl.h"
42e4b17023SJohn Marino #include "coverage.h"
43e4b17023SJohn Marino #include "ggc.h"
44e4b17023SJohn Marino #include "tree-flow.h"
45e4b17023SJohn Marino #include "ipa-prop.h"
46e4b17023SJohn Marino #include "ipa-inline.h"
47e4b17023SJohn Marino #include "tree-inline.h"
48e4b17023SJohn Marino #include "tree-pass.h"
49e4b17023SJohn Marino
50e4b17023SJohn Marino int ncalls_inlined;
51e4b17023SJohn Marino int nfunctions_inlined;
52e4b17023SJohn Marino
53e4b17023SJohn Marino /* Scale frequency of NODE edges by FREQ_SCALE. */
54e4b17023SJohn Marino
55e4b17023SJohn Marino static void
update_noncloned_frequencies(struct cgraph_node * node,int freq_scale)56e4b17023SJohn Marino update_noncloned_frequencies (struct cgraph_node *node,
57e4b17023SJohn Marino int freq_scale)
58e4b17023SJohn Marino {
59e4b17023SJohn Marino struct cgraph_edge *e;
60e4b17023SJohn Marino
61e4b17023SJohn Marino /* We do not want to ignore high loop nest after freq drops to 0. */
62e4b17023SJohn Marino if (!freq_scale)
63e4b17023SJohn Marino freq_scale = 1;
64e4b17023SJohn Marino for (e = node->callees; e; e = e->next_callee)
65e4b17023SJohn Marino {
66e4b17023SJohn Marino e->frequency = e->frequency * (gcov_type) freq_scale / CGRAPH_FREQ_BASE;
67e4b17023SJohn Marino if (e->frequency > CGRAPH_FREQ_MAX)
68e4b17023SJohn Marino e->frequency = CGRAPH_FREQ_MAX;
69e4b17023SJohn Marino if (!e->inline_failed)
70e4b17023SJohn Marino update_noncloned_frequencies (e->callee, freq_scale);
71e4b17023SJohn Marino }
72e4b17023SJohn Marino for (e = node->indirect_calls; e; e = e->next_callee)
73e4b17023SJohn Marino {
74e4b17023SJohn Marino e->frequency = e->frequency * (gcov_type) freq_scale / CGRAPH_FREQ_BASE;
75e4b17023SJohn Marino if (e->frequency > CGRAPH_FREQ_MAX)
76e4b17023SJohn Marino e->frequency = CGRAPH_FREQ_MAX;
77e4b17023SJohn Marino }
78e4b17023SJohn Marino }
79e4b17023SJohn Marino
80e4b17023SJohn Marino /* We removed or are going to remove the last call to NODE.
81e4b17023SJohn Marino Return true if we can and want proactively remove the NODE now.
82e4b17023SJohn Marino This is important to do, since we want inliner to know when offline
83e4b17023SJohn Marino copy of function was removed. */
84e4b17023SJohn Marino
85e4b17023SJohn Marino static bool
can_remove_node_now_p_1(struct cgraph_node * node)86e4b17023SJohn Marino can_remove_node_now_p_1 (struct cgraph_node *node)
87e4b17023SJohn Marino {
88e4b17023SJohn Marino /* FIXME: When address is taken of DECL_EXTERNAL function we still
89e4b17023SJohn Marino can remove its offline copy, but we would need to keep unanalyzed node in
90e4b17023SJohn Marino the callgraph so references can point to it. */
91e4b17023SJohn Marino return (!node->address_taken
92e4b17023SJohn Marino && !ipa_ref_has_aliases_p (&node->ref_list)
93e4b17023SJohn Marino && cgraph_can_remove_if_no_direct_calls_p (node)
94e4b17023SJohn Marino /* Inlining might enable more devirtualizing, so we want to remove
95e4b17023SJohn Marino those only after all devirtualizable virtual calls are processed.
96e4b17023SJohn Marino Lacking may edges in callgraph we just preserve them post
97e4b17023SJohn Marino inlining. */
98*5ce9237cSJohn Marino && !DECL_VIRTUAL_P (node->decl)
99e4b17023SJohn Marino /* During early inlining some unanalyzed cgraph nodes might be in the
100e4b17023SJohn Marino callgraph and they might reffer the function in question. */
101e4b17023SJohn Marino && !cgraph_new_nodes);
102e4b17023SJohn Marino }
103e4b17023SJohn Marino
104e4b17023SJohn Marino /* We are going to eliminate last direct call to NODE (or alias of it) via edge E.
105e4b17023SJohn Marino Verify that the NODE can be removed from unit and if it is contained in comdat
106e4b17023SJohn Marino group that the whole comdat group is removable. */
107e4b17023SJohn Marino
108e4b17023SJohn Marino static bool
can_remove_node_now_p(struct cgraph_node * node,struct cgraph_edge * e)109e4b17023SJohn Marino can_remove_node_now_p (struct cgraph_node *node, struct cgraph_edge *e)
110e4b17023SJohn Marino {
111e4b17023SJohn Marino struct cgraph_node *next;
112e4b17023SJohn Marino if (!can_remove_node_now_p_1 (node))
113e4b17023SJohn Marino return false;
114e4b17023SJohn Marino
115e4b17023SJohn Marino /* When we see same comdat group, we need to be sure that all
116e4b17023SJohn Marino items can be removed. */
117e4b17023SJohn Marino if (!node->same_comdat_group)
118e4b17023SJohn Marino return true;
119e4b17023SJohn Marino for (next = node->same_comdat_group;
120e4b17023SJohn Marino next != node; next = next->same_comdat_group)
121e4b17023SJohn Marino if ((next->callers && next->callers != e)
122e4b17023SJohn Marino || !can_remove_node_now_p_1 (next))
123e4b17023SJohn Marino return false;
124e4b17023SJohn Marino return true;
125e4b17023SJohn Marino }
126e4b17023SJohn Marino
127e4b17023SJohn Marino
128e4b17023SJohn Marino /* E is expected to be an edge being inlined. Clone destination node of
129e4b17023SJohn Marino the edge and redirect it to the new clone.
130e4b17023SJohn Marino DUPLICATE is used for bookkeeping on whether we are actually creating new
131e4b17023SJohn Marino clones or re-using node originally representing out-of-line function call.
132e4b17023SJohn Marino */
133e4b17023SJohn Marino
134e4b17023SJohn Marino void
clone_inlined_nodes(struct cgraph_edge * e,bool duplicate,bool update_original,int * overall_size)135e4b17023SJohn Marino clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
136e4b17023SJohn Marino bool update_original, int *overall_size)
137e4b17023SJohn Marino {
138e4b17023SJohn Marino if (duplicate)
139e4b17023SJohn Marino {
140e4b17023SJohn Marino /* We may eliminate the need for out-of-line copy to be output.
141e4b17023SJohn Marino In that case just go ahead and re-use it. This is not just an
142e4b17023SJohn Marino memory optimization. Making offline copy of fuction disappear
143e4b17023SJohn Marino from the program will improve future decisions on inlining. */
144e4b17023SJohn Marino if (!e->callee->callers->next_caller
145e4b17023SJohn Marino /* Recursive inlining never wants the master clone to
146e4b17023SJohn Marino be overwritten. */
147e4b17023SJohn Marino && update_original
148e4b17023SJohn Marino && can_remove_node_now_p (e->callee, e))
149e4b17023SJohn Marino {
150e4b17023SJohn Marino /* TODO: When callee is in a comdat group, we could remove all of it,
151e4b17023SJohn Marino including all inline clones inlined into it. That would however
152e4b17023SJohn Marino need small function inlining to register edge removal hook to
153e4b17023SJohn Marino maintain the priority queue.
154e4b17023SJohn Marino
155e4b17023SJohn Marino For now we keep the ohter functions in the group in program until
156e4b17023SJohn Marino cgraph_remove_unreachable_functions gets rid of them. */
157e4b17023SJohn Marino gcc_assert (!e->callee->global.inlined_to);
158e4b17023SJohn Marino if (e->callee->analyzed && !DECL_EXTERNAL (e->callee->decl))
159e4b17023SJohn Marino {
160e4b17023SJohn Marino if (overall_size)
161e4b17023SJohn Marino *overall_size -= inline_summary (e->callee)->size;
162e4b17023SJohn Marino nfunctions_inlined++;
163e4b17023SJohn Marino }
164e4b17023SJohn Marino duplicate = false;
165e4b17023SJohn Marino e->callee->local.externally_visible = false;
166e4b17023SJohn Marino update_noncloned_frequencies (e->callee, e->frequency);
167e4b17023SJohn Marino }
168e4b17023SJohn Marino else
169e4b17023SJohn Marino {
170e4b17023SJohn Marino struct cgraph_node *n;
171e4b17023SJohn Marino n = cgraph_clone_node (e->callee, e->callee->decl,
172e4b17023SJohn Marino e->count, e->frequency,
173e4b17023SJohn Marino update_original, NULL, true);
174e4b17023SJohn Marino cgraph_redirect_edge_callee (e, n);
175e4b17023SJohn Marino }
176e4b17023SJohn Marino }
177e4b17023SJohn Marino
178e4b17023SJohn Marino if (e->caller->global.inlined_to)
179e4b17023SJohn Marino e->callee->global.inlined_to = e->caller->global.inlined_to;
180e4b17023SJohn Marino else
181e4b17023SJohn Marino e->callee->global.inlined_to = e->caller;
182e4b17023SJohn Marino
183e4b17023SJohn Marino /* Recursively clone all bodies. */
184e4b17023SJohn Marino for (e = e->callee->callees; e; e = e->next_callee)
185e4b17023SJohn Marino if (!e->inline_failed)
186e4b17023SJohn Marino clone_inlined_nodes (e, duplicate, update_original, overall_size);
187e4b17023SJohn Marino }
188e4b17023SJohn Marino
189e4b17023SJohn Marino
190e4b17023SJohn Marino /* Mark edge E as inlined and update callgraph accordingly. UPDATE_ORIGINAL
191e4b17023SJohn Marino specify whether profile of original function should be updated. If any new
192e4b17023SJohn Marino indirect edges are discovered in the process, add them to NEW_EDGES, unless
193e4b17023SJohn Marino it is NULL. Return true iff any new callgraph edges were discovered as a
194e4b17023SJohn Marino result of inlining. */
195e4b17023SJohn Marino
196e4b17023SJohn Marino bool
inline_call(struct cgraph_edge * e,bool update_original,VEC (cgraph_edge_p,heap)** new_edges,int * overall_size)197e4b17023SJohn Marino inline_call (struct cgraph_edge *e, bool update_original,
198e4b17023SJohn Marino VEC (cgraph_edge_p, heap) **new_edges,
199e4b17023SJohn Marino int *overall_size)
200e4b17023SJohn Marino {
201e4b17023SJohn Marino int old_size = 0, new_size = 0;
202e4b17023SJohn Marino struct cgraph_node *to = NULL;
203e4b17023SJohn Marino struct cgraph_edge *curr = e;
204e4b17023SJohn Marino struct cgraph_node *callee = cgraph_function_or_thunk_node (e->callee, NULL);
205e4b17023SJohn Marino
206e4b17023SJohn Marino /* Don't inline inlined edges. */
207e4b17023SJohn Marino gcc_assert (e->inline_failed);
208e4b17023SJohn Marino /* Don't even think of inlining inline clone. */
209e4b17023SJohn Marino gcc_assert (!callee->global.inlined_to);
210e4b17023SJohn Marino
211e4b17023SJohn Marino e->inline_failed = CIF_OK;
212e4b17023SJohn Marino DECL_POSSIBLY_INLINED (callee->decl) = true;
213e4b17023SJohn Marino
214e4b17023SJohn Marino to = e->caller;
215e4b17023SJohn Marino if (to->global.inlined_to)
216e4b17023SJohn Marino to = to->global.inlined_to;
217e4b17023SJohn Marino
218e4b17023SJohn Marino /* If aliases are involved, redirect edge to the actual destination and
219e4b17023SJohn Marino possibly remove the aliases. */
220e4b17023SJohn Marino if (e->callee != callee)
221e4b17023SJohn Marino {
222e4b17023SJohn Marino struct cgraph_node *alias = e->callee, *next_alias;
223e4b17023SJohn Marino cgraph_redirect_edge_callee (e, callee);
224e4b17023SJohn Marino while (alias && alias != callee)
225e4b17023SJohn Marino {
226e4b17023SJohn Marino if (!alias->callers
227e4b17023SJohn Marino && can_remove_node_now_p (alias, e))
228e4b17023SJohn Marino {
229e4b17023SJohn Marino next_alias = cgraph_alias_aliased_node (alias);
230e4b17023SJohn Marino cgraph_remove_node (alias);
231e4b17023SJohn Marino alias = next_alias;
232e4b17023SJohn Marino }
233e4b17023SJohn Marino else
234e4b17023SJohn Marino break;
235e4b17023SJohn Marino }
236e4b17023SJohn Marino }
237e4b17023SJohn Marino
238e4b17023SJohn Marino clone_inlined_nodes (e, true, update_original, overall_size);
239e4b17023SJohn Marino
240e4b17023SJohn Marino gcc_assert (curr->callee->global.inlined_to == to);
241e4b17023SJohn Marino
242e4b17023SJohn Marino old_size = inline_summary (to)->size;
243e4b17023SJohn Marino inline_merge_summary (e);
244e4b17023SJohn Marino new_size = inline_summary (to)->size;
245e4b17023SJohn Marino if (overall_size)
246e4b17023SJohn Marino *overall_size += new_size - old_size;
247e4b17023SJohn Marino ncalls_inlined++;
248e4b17023SJohn Marino
249e4b17023SJohn Marino /* This must happen after inline_merge_summary that rely on jump
250e4b17023SJohn Marino functions of callee to not be updated. */
251e4b17023SJohn Marino if (optimize)
252e4b17023SJohn Marino return ipa_propagate_indirect_call_infos (curr, new_edges);
253e4b17023SJohn Marino else
254e4b17023SJohn Marino return false;
255e4b17023SJohn Marino }
256e4b17023SJohn Marino
257e4b17023SJohn Marino
258e4b17023SJohn Marino /* Copy function body of NODE and redirect all inline clones to it.
259e4b17023SJohn Marino This is done before inline plan is applied to NODE when there are
260e4b17023SJohn Marino still some inline clones if it.
261e4b17023SJohn Marino
262e4b17023SJohn Marino This is neccesary because inline decisions are not really transitive
263e4b17023SJohn Marino and the other inline clones may have different bodies. */
264e4b17023SJohn Marino
265e4b17023SJohn Marino static struct cgraph_node *
save_inline_function_body(struct cgraph_node * node)266e4b17023SJohn Marino save_inline_function_body (struct cgraph_node *node)
267e4b17023SJohn Marino {
268e4b17023SJohn Marino struct cgraph_node *first_clone, *n;
269e4b17023SJohn Marino
270e4b17023SJohn Marino if (dump_file)
271e4b17023SJohn Marino fprintf (dump_file, "\nSaving body of %s for later reuse\n",
272e4b17023SJohn Marino cgraph_node_name (node));
273e4b17023SJohn Marino
274e4b17023SJohn Marino gcc_assert (node == cgraph_get_node (node->decl));
275e4b17023SJohn Marino
276e4b17023SJohn Marino /* first_clone will be turned into real function. */
277e4b17023SJohn Marino first_clone = node->clones;
278e4b17023SJohn Marino first_clone->decl = copy_node (node->decl);
279e4b17023SJohn Marino cgraph_insert_node_to_hashtable (first_clone);
280e4b17023SJohn Marino gcc_assert (first_clone == cgraph_get_node (first_clone->decl));
281e4b17023SJohn Marino
282e4b17023SJohn Marino /* Now reshape the clone tree, so all other clones descends from
283e4b17023SJohn Marino first_clone. */
284e4b17023SJohn Marino if (first_clone->next_sibling_clone)
285e4b17023SJohn Marino {
286e4b17023SJohn Marino for (n = first_clone->next_sibling_clone; n->next_sibling_clone; n = n->next_sibling_clone)
287e4b17023SJohn Marino n->clone_of = first_clone;
288e4b17023SJohn Marino n->clone_of = first_clone;
289e4b17023SJohn Marino n->next_sibling_clone = first_clone->clones;
290e4b17023SJohn Marino if (first_clone->clones)
291e4b17023SJohn Marino first_clone->clones->prev_sibling_clone = n;
292e4b17023SJohn Marino first_clone->clones = first_clone->next_sibling_clone;
293e4b17023SJohn Marino first_clone->next_sibling_clone->prev_sibling_clone = NULL;
294e4b17023SJohn Marino first_clone->next_sibling_clone = NULL;
295e4b17023SJohn Marino gcc_assert (!first_clone->prev_sibling_clone);
296e4b17023SJohn Marino }
297e4b17023SJohn Marino first_clone->clone_of = NULL;
298e4b17023SJohn Marino
299e4b17023SJohn Marino /* Now node in question has no clones. */
300e4b17023SJohn Marino node->clones = NULL;
301e4b17023SJohn Marino
302e4b17023SJohn Marino /* Inline clones share decl with the function they are cloned
303e4b17023SJohn Marino from. Walk the whole clone tree and redirect them all to the
304e4b17023SJohn Marino new decl. */
305e4b17023SJohn Marino if (first_clone->clones)
306e4b17023SJohn Marino for (n = first_clone->clones; n != first_clone;)
307e4b17023SJohn Marino {
308e4b17023SJohn Marino gcc_assert (n->decl == node->decl);
309e4b17023SJohn Marino n->decl = first_clone->decl;
310e4b17023SJohn Marino if (n->clones)
311e4b17023SJohn Marino n = n->clones;
312e4b17023SJohn Marino else if (n->next_sibling_clone)
313e4b17023SJohn Marino n = n->next_sibling_clone;
314e4b17023SJohn Marino else
315e4b17023SJohn Marino {
316e4b17023SJohn Marino while (n != first_clone && !n->next_sibling_clone)
317e4b17023SJohn Marino n = n->clone_of;
318e4b17023SJohn Marino if (n != first_clone)
319e4b17023SJohn Marino n = n->next_sibling_clone;
320e4b17023SJohn Marino }
321e4b17023SJohn Marino }
322e4b17023SJohn Marino
323e4b17023SJohn Marino /* Copy the OLD_VERSION_NODE function tree to the new version. */
324e4b17023SJohn Marino tree_function_versioning (node->decl, first_clone->decl, NULL, true, NULL,
325e4b17023SJohn Marino false, NULL, NULL);
326e4b17023SJohn Marino
327e4b17023SJohn Marino /* The function will be short lived and removed after we inline all the clones,
328e4b17023SJohn Marino but make it internal so we won't confuse ourself. */
329e4b17023SJohn Marino DECL_EXTERNAL (first_clone->decl) = 0;
330e4b17023SJohn Marino DECL_COMDAT_GROUP (first_clone->decl) = NULL_TREE;
331e4b17023SJohn Marino TREE_PUBLIC (first_clone->decl) = 0;
332e4b17023SJohn Marino DECL_COMDAT (first_clone->decl) = 0;
333e4b17023SJohn Marino VEC_free (ipa_opt_pass, heap,
334e4b17023SJohn Marino first_clone->ipa_transforms_to_apply);
335e4b17023SJohn Marino first_clone->ipa_transforms_to_apply = NULL;
336e4b17023SJohn Marino
337e4b17023SJohn Marino #ifdef ENABLE_CHECKING
338e4b17023SJohn Marino verify_cgraph_node (first_clone);
339e4b17023SJohn Marino #endif
340e4b17023SJohn Marino return first_clone;
341e4b17023SJohn Marino }
342e4b17023SJohn Marino
343e4b17023SJohn Marino
344e4b17023SJohn Marino /* Apply inline plan to function. */
345e4b17023SJohn Marino
346e4b17023SJohn Marino unsigned int
inline_transform(struct cgraph_node * node)347e4b17023SJohn Marino inline_transform (struct cgraph_node *node)
348e4b17023SJohn Marino {
349e4b17023SJohn Marino unsigned int todo = 0;
350e4b17023SJohn Marino struct cgraph_edge *e;
351e4b17023SJohn Marino
352e4b17023SJohn Marino /* FIXME: Currently the pass manager is adding inline transform more than
353e4b17023SJohn Marino once to some clones. This needs revisiting after WPA cleanups. */
354e4b17023SJohn Marino if (cfun->after_inlining)
355e4b17023SJohn Marino return 0;
356e4b17023SJohn Marino
357e4b17023SJohn Marino /* We might need the body of this function so that we can expand
358e4b17023SJohn Marino it inline somewhere else. */
359e4b17023SJohn Marino if (cgraph_preserve_function_body_p (node))
360e4b17023SJohn Marino save_inline_function_body (node);
361e4b17023SJohn Marino
362e4b17023SJohn Marino for (e = node->callees; e; e = e->next_callee)
363e4b17023SJohn Marino cgraph_redirect_edge_call_stmt_to_callee (e);
364e4b17023SJohn Marino
365e4b17023SJohn Marino timevar_push (TV_INTEGRATION);
366e4b17023SJohn Marino if (node->callees)
367e4b17023SJohn Marino todo = optimize_inline_calls (current_function_decl);
368e4b17023SJohn Marino timevar_pop (TV_INTEGRATION);
369e4b17023SJohn Marino
370e4b17023SJohn Marino cfun->always_inline_functions_inlined = true;
371e4b17023SJohn Marino cfun->after_inlining = true;
372e4b17023SJohn Marino todo |= execute_fixup_cfg ();
373e4b17023SJohn Marino
374e4b17023SJohn Marino if (!(todo & TODO_update_ssa_any))
375e4b17023SJohn Marino /* Redirecting edges might lead to a need for vops to be recomputed. */
376e4b17023SJohn Marino todo |= TODO_update_ssa_only_virtuals;
377e4b17023SJohn Marino
378e4b17023SJohn Marino return todo;
379e4b17023SJohn Marino }
380