xref: /dflybsd-src/contrib/gcc-4.7/gcc/ipa-inline-transform.c (revision 81fc95a5293ee307c688a350a3feb4734aaddbb4)
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