]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ipa-inline-transform.c
Add MOVBE and RDRND for AMD bdver4
[thirdparty/gcc.git] / gcc / ipa-inline-transform.c
CommitLineData
fee8b6da 1/* Callgraph transformations to handle inlining
23a5b65a 2 Copyright (C) 2003-2014 Free Software Foundation, Inc.
fee8b6da
JH
3 Contributed by Jan Hubicka
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21/* The inline decisions are stored in callgraph in "inline plan" and
22 applied later.
23
24 To mark given call inline, use inline_call function.
25 The function marks the edge inlinable and, if necessary, produces
26 virtual clone in the callgraph representing the new copy of callee's
27 function body.
28
29 The inline plan is applied on given function body by inline_transform. */
30
31#include "config.h"
32#include "system.h"
33#include "coretypes.h"
34#include "tm.h"
35#include "tree.h"
36#include "langhooks.h"
fee8b6da
JH
37#include "intl.h"
38#include "coverage.h"
39#include "ggc.h"
442b4905 40#include "tree-cfg.h"
fee8b6da
JH
41#include "ipa-prop.h"
42#include "ipa-inline.h"
43#include "tree-inline.h"
516e0768 44#include "tree-pass.h"
fee8b6da
JH
45
46int ncalls_inlined;
47int nfunctions_inlined;
09ce3660 48bool speculation_removed;
fee8b6da 49
898b8927 50/* Scale frequency of NODE edges by FREQ_SCALE. */
fee8b6da
JH
51
52static void
53update_noncloned_frequencies (struct cgraph_node *node,
898b8927 54 int freq_scale)
fee8b6da
JH
55{
56 struct cgraph_edge *e;
57
58 /* We do not want to ignore high loop nest after freq drops to 0. */
59 if (!freq_scale)
60 freq_scale = 1;
61 for (e = node->callees; e; e = e->next_callee)
62 {
fee8b6da
JH
63 e->frequency = e->frequency * (gcov_type) freq_scale / CGRAPH_FREQ_BASE;
64 if (e->frequency > CGRAPH_FREQ_MAX)
65 e->frequency = CGRAPH_FREQ_MAX;
66 if (!e->inline_failed)
898b8927
JH
67 update_noncloned_frequencies (e->callee, freq_scale);
68 }
69 for (e = node->indirect_calls; e; e = e->next_callee)
70 {
71 e->frequency = e->frequency * (gcov_type) freq_scale / CGRAPH_FREQ_BASE;
72 if (e->frequency > CGRAPH_FREQ_MAX)
73 e->frequency = CGRAPH_FREQ_MAX;
fee8b6da
JH
74 }
75}
76
a5b1779f
JH
77/* We removed or are going to remove the last call to NODE.
78 Return true if we can and want proactively remove the NODE now.
79 This is important to do, since we want inliner to know when offline
80 copy of function was removed. */
81
82static bool
6c69a029 83can_remove_node_now_p_1 (struct cgraph_node *node)
a5b1779f
JH
84{
85 /* FIXME: When address is taken of DECL_EXTERNAL function we still
86 can remove its offline copy, but we would need to keep unanalyzed node in
87 the callgraph so references can point to it. */
67348ccc 88 return (!node->address_taken
d122681a 89 && !node->has_aliases_p ()
c0c123ef 90 && !node->used_as_abstract_origin
d52f5295 91 && node->can_remove_if_no_direct_calls_p ()
a5b1779f
JH
92 /* Inlining might enable more devirtualizing, so we want to remove
93 those only after all devirtualizable virtual calls are processed.
94 Lacking may edges in callgraph we just preserve them post
95 inlining. */
67348ccc 96 && !DECL_VIRTUAL_P (node->decl)
a5b1779f
JH
97 /* During early inlining some unanalyzed cgraph nodes might be in the
98 callgraph and they might reffer the function in question. */
99 && !cgraph_new_nodes);
100}
101
6c69a029
JH
102/* We are going to eliminate last direct call to NODE (or alias of it) via edge E.
103 Verify that the NODE can be removed from unit and if it is contained in comdat
104 group that the whole comdat group is removable. */
105
106static bool
107can_remove_node_now_p (struct cgraph_node *node, struct cgraph_edge *e)
108{
109 struct cgraph_node *next;
110 if (!can_remove_node_now_p_1 (node))
111 return false;
112
113 /* When we see same comdat group, we need to be sure that all
114 items can be removed. */
67348ccc 115 if (!node->same_comdat_group)
6c69a029 116 return true;
d52f5295
ML
117 for (next = dyn_cast<cgraph_node *> (node->same_comdat_group);
118 next != node; next = dyn_cast<cgraph_node *> (next->same_comdat_group))
aa74f081
JH
119 if ((next->callers && next->callers != e)
120 || !can_remove_node_now_p_1 (next))
6c69a029
JH
121 return false;
122 return true;
123}
124
fee8b6da
JH
125
126/* E is expected to be an edge being inlined. Clone destination node of
127 the edge and redirect it to the new clone.
128 DUPLICATE is used for bookkeeping on whether we are actually creating new
129 clones or re-using node originally representing out-of-line function call.
bd936951
JH
130 By default the offline copy is removed, when it appears dead after inlining.
131 UPDATE_ORIGINAL prevents this transformation.
132 If OVERALL_SIZE is non-NULL, the size is updated to reflect the
133 transformation.
134 FREQ_SCALE specify the scaling of frequencies of call sites. */
fee8b6da
JH
135
136void
137clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
bd936951 138 bool update_original, int *overall_size, int freq_scale)
fee8b6da 139{
44a60244 140 struct cgraph_node *inlining_into;
09ce3660 141 struct cgraph_edge *next;
44a60244
MJ
142
143 if (e->caller->global.inlined_to)
144 inlining_into = e->caller->global.inlined_to;
145 else
146 inlining_into = e->caller;
147
fee8b6da
JH
148 if (duplicate)
149 {
150 /* We may eliminate the need for out-of-line copy to be output.
151 In that case just go ahead and re-use it. This is not just an
152 memory optimization. Making offline copy of fuction disappear
153 from the program will improve future decisions on inlining. */
154 if (!e->callee->callers->next_caller
155 /* Recursive inlining never wants the master clone to
156 be overwritten. */
157 && update_original
6c69a029 158 && can_remove_node_now_p (e->callee, e))
fee8b6da 159 {
6c69a029
JH
160 /* TODO: When callee is in a comdat group, we could remove all of it,
161 including all inline clones inlined into it. That would however
162 need small function inlining to register edge removal hook to
163 maintain the priority queue.
164
165 For now we keep the ohter functions in the group in program until
166 cgraph_remove_unreachable_functions gets rid of them. */
fee8b6da 167 gcc_assert (!e->callee->global.inlined_to);
d52f5295 168 e->callee->dissolve_same_comdat_group_list ();
67348ccc 169 if (e->callee->definition && !DECL_EXTERNAL (e->callee->decl))
fee8b6da
JH
170 {
171 if (overall_size)
172 *overall_size -= inline_summary (e->callee)->size;
173 nfunctions_inlined++;
174 }
175 duplicate = false;
67348ccc 176 e->callee->externally_visible = false;
898b8927 177 update_noncloned_frequencies (e->callee, e->frequency);
fee8b6da
JH
178 }
179 else
180 {
181 struct cgraph_node *n;
bd936951
JH
182
183 if (freq_scale == -1)
184 freq_scale = e->frequency;
d52f5295
ML
185 n = e->callee->create_clone (e->callee->decl,
186 MIN (e->count, e->callee->count),
187 freq_scale,
188 update_original, vNULL, true,
189 inlining_into,
190 NULL);
fee8b6da
JH
191 cgraph_redirect_edge_callee (e, n);
192 }
193 }
65d630d4 194 else
d52f5295 195 e->callee->dissolve_same_comdat_group_list ();
fee8b6da 196
44a60244 197 e->callee->global.inlined_to = inlining_into;
fee8b6da
JH
198
199 /* Recursively clone all bodies. */
09ce3660
JH
200 for (e = e->callee->callees; e; e = next)
201 {
202 next = e->next_callee;
203 if (!e->inline_failed)
bd936951 204 clone_inlined_nodes (e, duplicate, update_original, overall_size, freq_scale);
09ce3660
JH
205 if (e->speculative && !speculation_useful_p (e, true))
206 {
207 cgraph_resolve_speculation (e, NULL);
208 speculation_removed = true;
209 }
210 }
fee8b6da
JH
211}
212
213
214/* Mark edge E as inlined and update callgraph accordingly. UPDATE_ORIGINAL
215 specify whether profile of original function should be updated. If any new
216 indirect edges are discovered in the process, add them to NEW_EDGES, unless
c170d40f
JH
217 it is NULL. If UPDATE_OVERALL_SUMMARY is false, do not bother to recompute overall
218 size of caller after inlining. Caller is required to eventually do it via
219 inline_update_overall_summary.
1bbb87c4 220 If callee_removed is non-NULL, set it to true if we removed callee node.
c170d40f
JH
221
222 Return true iff any new callgraph edges were discovered as a
fee8b6da
JH
223 result of inlining. */
224
225bool
226inline_call (struct cgraph_edge *e, bool update_original,
d52f5295 227 vec<cgraph_edge *> *new_edges,
1bbb87c4
JH
228 int *overall_size, bool update_overall_summary,
229 bool *callee_removed)
fee8b6da
JH
230{
231 int old_size = 0, new_size = 0;
232 struct cgraph_node *to = NULL;
233 struct cgraph_edge *curr = e;
d52f5295 234 struct cgraph_node *callee = e->callee->ultimate_alias_target ();
0f378cb5
JH
235 bool new_edges_found = false;
236
d250540a 237#ifdef ENABLE_CHECKING
0f378cb5
JH
238 int estimated_growth = estimate_edge_growth (e);
239 bool predicated = inline_edge_summary (e)->predicate != NULL;
240#endif
fee8b6da 241
09ce3660 242 speculation_removed = false;
fee8b6da
JH
243 /* Don't inline inlined edges. */
244 gcc_assert (e->inline_failed);
245 /* Don't even think of inlining inline clone. */
a5b1779f 246 gcc_assert (!callee->global.inlined_to);
fee8b6da
JH
247
248 e->inline_failed = CIF_OK;
67348ccc 249 DECL_POSSIBLY_INLINED (callee->decl) = true;
fee8b6da 250
632b4f8e
JH
251 to = e->caller;
252 if (to->global.inlined_to)
253 to = to->global.inlined_to;
632b4f8e 254
a5b1779f
JH
255 /* If aliases are involved, redirect edge to the actual destination and
256 possibly remove the aliases. */
257 if (e->callee != callee)
39e2db00
JH
258 {
259 struct cgraph_node *alias = e->callee, *next_alias;
260 cgraph_redirect_edge_callee (e, callee);
261 while (alias && alias != callee)
262 {
263 if (!alias->callers
6c69a029 264 && can_remove_node_now_p (alias, e))
39e2db00 265 {
d52f5295
ML
266 next_alias = alias->get_alias_target ();
267 alias->remove ();
1bbb87c4
JH
268 if (callee_removed)
269 *callee_removed = true;
39e2db00
JH
270 alias = next_alias;
271 }
272 else
273 break;
274 }
275 }
a5b1779f 276
bd936951 277 clone_inlined_nodes (e, true, update_original, overall_size, e->frequency);
fee8b6da 278
fee8b6da 279 gcc_assert (curr->callee->global.inlined_to == to);
898b8927
JH
280
281 old_size = inline_summary (to)->size;
282 inline_merge_summary (e);
0f378cb5
JH
283 if (optimize)
284 new_edges_found = ipa_propagate_indirect_call_infos (curr, new_edges);
c170d40f
JH
285 if (update_overall_summary)
286 inline_update_overall_summary (to);
898b8927 287 new_size = inline_summary (to)->size;
d250540a 288
1f26ac87
JM
289 if (callee->calls_comdat_local)
290 to->calls_comdat_local = true;
d52f5295 291 else if (to->calls_comdat_local && callee->comdat_local_p ())
1f26ac87
JM
292 {
293 struct cgraph_edge *se = to->callees;
294 for (; se; se = se->next_callee)
d52f5295 295 if (se->inline_failed && se->callee->comdat_local_p ())
1f26ac87
JM
296 break;
297 if (se == NULL)
298 to->calls_comdat_local = false;
299 }
300
d250540a 301#ifdef ENABLE_CHECKING
0f378cb5
JH
302 /* Verify that estimated growth match real growth. Allow off-by-one
303 error due to INLINE_SIZE_SCALE roudoff errors. */
48b1474e 304 gcc_assert (!update_overall_summary || !overall_size || new_edges_found
0f378cb5 305 || abs (estimated_growth - (new_size - old_size)) <= 1
09ce3660 306 || speculation_removed
0f378cb5
JH
307 /* FIXME: a hack. Edges with false predicate are accounted
308 wrong, we should remove them from callgraph. */
309 || predicated);
310#endif
d250540a 311
8256d5ca
JH
312 /* Account the change of overall unit size; external functions will be
313 removed and are thus not accounted. */
314 if (overall_size
67348ccc 315 && !DECL_EXTERNAL (to->decl))
fee8b6da
JH
316 *overall_size += new_size - old_size;
317 ncalls_inlined++;
318
25837a2f
JH
319 /* This must happen after inline_merge_summary that rely on jump
320 functions of callee to not be updated. */
0f378cb5 321 return new_edges_found;
fee8b6da
JH
322}
323
324
325/* Copy function body of NODE and redirect all inline clones to it.
326 This is done before inline plan is applied to NODE when there are
327 still some inline clones if it.
328
073a8998 329 This is necessary because inline decisions are not really transitive
fee8b6da
JH
330 and the other inline clones may have different bodies. */
331
332static struct cgraph_node *
333save_inline_function_body (struct cgraph_node *node)
334{
335 struct cgraph_node *first_clone, *n;
336
337 if (dump_file)
338 fprintf (dump_file, "\nSaving body of %s for later reuse\n",
fec39fa6 339 node->name ());
fee8b6da 340
d52f5295 341 gcc_assert (node == cgraph_node::get (node->decl));
fee8b6da
JH
342
343 /* first_clone will be turned into real function. */
344 first_clone = node->clones;
67348ccc 345 first_clone->decl = copy_node (node->decl);
aede2c10 346 first_clone->decl->decl_with_vis.symtab_node = first_clone;
d52f5295 347 gcc_assert (first_clone == cgraph_node::get (first_clone->decl));
fee8b6da
JH
348
349 /* Now reshape the clone tree, so all other clones descends from
350 first_clone. */
351 if (first_clone->next_sibling_clone)
352 {
353 for (n = first_clone->next_sibling_clone; n->next_sibling_clone; n = n->next_sibling_clone)
354 n->clone_of = first_clone;
355 n->clone_of = first_clone;
356 n->next_sibling_clone = first_clone->clones;
357 if (first_clone->clones)
358 first_clone->clones->prev_sibling_clone = n;
359 first_clone->clones = first_clone->next_sibling_clone;
360 first_clone->next_sibling_clone->prev_sibling_clone = NULL;
361 first_clone->next_sibling_clone = NULL;
362 gcc_assert (!first_clone->prev_sibling_clone);
363 }
364 first_clone->clone_of = NULL;
365
366 /* Now node in question has no clones. */
367 node->clones = NULL;
368
1a3118e9
JH
369 /* Inline clones share decl with the function they are cloned
370 from. Walk the whole clone tree and redirect them all to the
371 new decl. */
fee8b6da
JH
372 if (first_clone->clones)
373 for (n = first_clone->clones; n != first_clone;)
374 {
67348ccc
DM
375 gcc_assert (n->decl == node->decl);
376 n->decl = first_clone->decl;
fee8b6da
JH
377 if (n->clones)
378 n = n->clones;
379 else if (n->next_sibling_clone)
380 n = n->next_sibling_clone;
381 else
382 {
383 while (n != first_clone && !n->next_sibling_clone)
384 n = n->clone_of;
385 if (n != first_clone)
386 n = n->next_sibling_clone;
387 }
388 }
389
390 /* Copy the OLD_VERSION_NODE function tree to the new version. */
67348ccc 391 tree_function_versioning (node->decl, first_clone->decl,
9771b263
DN
392 NULL, true, NULL, false,
393 NULL, NULL);
fee8b6da 394
1a3118e9
JH
395 /* The function will be short lived and removed after we inline all the clones,
396 but make it internal so we won't confuse ourself. */
67348ccc 397 DECL_EXTERNAL (first_clone->decl) = 0;
67348ccc
DM
398 TREE_PUBLIC (first_clone->decl) = 0;
399 DECL_COMDAT (first_clone->decl) = 0;
9771b263 400 first_clone->ipa_transforms_to_apply.release ();
fee8b6da 401
b4e93f45
JH
402 /* When doing recursive inlining, the clone may become unnecessary.
403 This is possible i.e. in the case when the recursive function is proved to be
404 non-throwing and the recursion happens only in the EH landing pad.
405 We can not remove the clone until we are done with saving the body.
406 Remove it now. */
407 if (!first_clone->callers)
408 {
d52f5295 409 first_clone->remove_symbol_and_inline_clones ();
b4e93f45
JH
410 first_clone = NULL;
411 }
fee8b6da 412#ifdef ENABLE_CHECKING
b4e93f45 413 else
d52f5295 414 first_clone->verify ();
fee8b6da
JH
415#endif
416 return first_clone;
417}
418
9c8305f8
JH
419/* Return true when function body of DECL still needs to be kept around
420 for later re-use. */
65d630d4 421static bool
9c8305f8
JH
422preserve_function_body_p (struct cgraph_node *node)
423{
424 gcc_assert (cgraph_global_info_ready);
67348ccc 425 gcc_assert (!node->alias && !node->thunk.thunk_p);
9c8305f8
JH
426
427 /* Look if there is any clone around. */
428 if (node->clones)
429 return true;
430 return false;
431}
fee8b6da
JH
432
433/* Apply inline plan to function. */
434
435unsigned int
436inline_transform (struct cgraph_node *node)
437{
438 unsigned int todo = 0;
e8aec975 439 struct cgraph_edge *e, *next;
c9fc06dc 440
fee8b6da
JH
441 /* FIXME: Currently the pass manager is adding inline transform more than
442 once to some clones. This needs revisiting after WPA cleanups. */
443 if (cfun->after_inlining)
444 return 0;
445
446 /* We might need the body of this function so that we can expand
447 it inline somewhere else. */
9c8305f8 448 if (preserve_function_body_p (node))
fee8b6da
JH
449 save_inline_function_body (node);
450
e8aec975
JH
451 for (e = node->callees; e; e = next)
452 {
453 next = e->next_callee;
454 cgraph_redirect_edge_call_stmt_to_callee (e);
455 }
d122681a 456 node->remove_all_references ();
c9fc06dc
CB
457
458 timevar_push (TV_INTEGRATION);
07d6cd64 459 if (node->callees && optimize)
55f01229 460 todo = optimize_inline_calls (current_function_decl);
c9fc06dc
CB
461 timevar_pop (TV_INTEGRATION);
462
f8698b37
RG
463 cfun->always_inline_functions_inlined = true;
464 cfun->after_inlining = true;
465 todo |= execute_fixup_cfg ();
466
55f01229
RG
467 if (!(todo & TODO_update_ssa_any))
468 /* Redirecting edges might lead to a need for vops to be recomputed. */
469 todo |= TODO_update_ssa_only_virtuals;
470
f8698b37 471 return todo;
fee8b6da 472}