1 /* Analysis used by inlining decision heuristics.
2 Copyright (C) 2003-2024 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 3, 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 COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
27 #include "alloc-pool.h"
28 #include "tree-pass.h"
30 #include "tree-streamer.h"
32 #include "diagnostic.h"
33 #include "fold-const.h"
34 #include "print-tree.h"
35 #include "tree-inline.h"
36 #include "gimple-pretty-print.h"
38 #include "gimple-iterator.h"
40 #include "tree-ssa-loop-niter.h"
41 #include "tree-ssa-loop.h"
42 #include "symbol-summary.h"
44 #include "ipa-fnsummary.h"
45 #include "ipa-inline.h"
47 #include "tree-scalar-evolution.h"
48 #include "ipa-utils.h"
49 #include "cfgexpand.h"
53 /* Cached node/edge growths. */
54 fast_call_summary
<edge_growth_cache_entry
*, va_heap
> *edge_growth_cache
= NULL
;
56 /* The context cache remembers estimated time/size and hints for given
57 ipa_call_context of a call. */
58 class node_context_cache_entry
61 ipa_cached_call_context ctx
;
62 sreal time
, nonspec_time
;
66 node_context_cache_entry ()
70 ~node_context_cache_entry ()
76 /* At the moment we implement primitive single entry LRU cache. */
77 class node_context_summary
80 node_context_cache_entry entry
;
82 node_context_summary ()
86 ~node_context_summary ()
91 /* Summary holding the context cache. */
92 static fast_function_summary
<node_context_summary
*, va_heap
>
93 *node_context_cache
= NULL
;
94 /* Statistics about the context cache effectivity. */
95 static long node_context_cache_hit
, node_context_cache_miss
,
96 node_context_cache_clear
;
98 /* Give initial reasons why inlining would fail on EDGE. This gets either
99 nullified or usually overwritten by more precise reasons later. */
102 initialize_inline_failed (struct cgraph_edge
*e
)
104 struct cgraph_node
*callee
= e
->callee
;
106 if (e
->inline_failed
&& e
->inline_failed
!= CIF_BODY_NOT_AVAILABLE
107 && cgraph_inline_failed_type (e
->inline_failed
) == CIF_FINAL_ERROR
)
109 else if (e
->indirect_unknown_callee
)
110 e
->inline_failed
= CIF_INDIRECT_UNKNOWN_CALL
;
111 else if (!callee
->definition
)
112 e
->inline_failed
= CIF_BODY_NOT_AVAILABLE
;
113 else if (callee
->redefined_extern_inline
)
114 e
->inline_failed
= CIF_REDEFINED_EXTERN_INLINE
;
116 e
->inline_failed
= CIF_FUNCTION_NOT_CONSIDERED
;
117 gcc_checking_assert (!e
->call_stmt_cannot_inline_p
118 || cgraph_inline_failed_type (e
->inline_failed
)
122 /* Allocate edge growth caches. */
125 initialize_growth_caches ()
128 = new fast_call_summary
<edge_growth_cache_entry
*, va_heap
> (symtab
);
130 = new fast_function_summary
<node_context_summary
*, va_heap
> (symtab
);
131 edge_growth_cache
->disable_duplication_hook ();
132 node_context_cache
->disable_insertion_hook ();
133 node_context_cache
->disable_duplication_hook ();
136 /* Free growth caches. */
139 free_growth_caches (void)
141 delete edge_growth_cache
;
142 delete node_context_cache
;
143 edge_growth_cache
= NULL
;
144 node_context_cache
= NULL
;
146 fprintf (dump_file
, "node context cache: %li hits, %li misses,"
147 " %li initializations\n",
148 node_context_cache_hit
, node_context_cache_miss
,
149 node_context_cache_clear
);
150 node_context_cache_hit
= 0;
151 node_context_cache_miss
= 0;
152 node_context_cache_clear
= 0;
155 /* Return hints derived from EDGE. */
158 simple_edge_hints (struct cgraph_edge
*edge
)
161 struct cgraph_node
*to
= (edge
->caller
->inlined_to
162 ? edge
->caller
->inlined_to
: edge
->caller
);
163 struct cgraph_node
*callee
= edge
->callee
->ultimate_alias_target ();
164 int to_scc_no
= ipa_fn_summaries
->get (to
)->scc_no
;
165 int callee_scc_no
= ipa_fn_summaries
->get (callee
)->scc_no
;
167 if (to_scc_no
&& to_scc_no
== callee_scc_no
&& !edge
->recursive_p ())
168 hints
|= INLINE_HINT_same_scc
;
170 if (cross_module_call_p (edge
))
171 hints
|= INLINE_HINT_cross_module
;
176 /* Estimate the time cost for the caller when inlining EDGE.
177 Only to be called via estimate_edge_time, that handles the
180 When caching, also update the cache entry. Compute both time and
181 size, since we always need both metrics eventually. */
184 do_estimate_edge_time (struct cgraph_edge
*edge
, sreal
*ret_nonspec_time
)
186 sreal time
, nonspec_time
;
189 struct cgraph_node
*callee
;
190 clause_t clause
, nonspec_clause
;
191 ipa_auto_call_arg_values avals
;
192 class ipa_call_summary
*es
= ipa_call_summaries
->get (edge
);
195 callee
= edge
->callee
->ultimate_alias_target ();
197 gcc_checking_assert (edge
->inline_failed
);
198 evaluate_properties_for_edge (edge
, true, &clause
, &nonspec_clause
,
200 ipa_call_context
ctx (callee
, clause
, nonspec_clause
, es
->param
, &avals
);
201 if (node_context_cache
!= NULL
)
203 node_context_summary
*e
= node_context_cache
->get_create (callee
);
204 if (e
->entry
.ctx
.equal_to (ctx
))
206 node_context_cache_hit
++;
207 size
= e
->entry
.size
;
208 time
= e
->entry
.time
;
209 nonspec_time
= e
->entry
.nonspec_time
;
210 hints
= e
->entry
.hints
;
212 && !opt_for_fn (callee
->decl
, flag_profile_partial_training
)
213 && !callee
->count
.ipa_p ())
215 ipa_call_estimates chk_estimates
;
216 ctx
.estimate_size_and_time (&chk_estimates
);
217 gcc_assert (chk_estimates
.size
== size
218 && chk_estimates
.time
== time
219 && chk_estimates
.nonspecialized_time
== nonspec_time
220 && chk_estimates
.hints
== hints
);
225 if (e
->entry
.ctx
.exists_p ())
226 node_context_cache_miss
++;
228 node_context_cache_clear
++;
229 e
->entry
.ctx
.release ();
230 ipa_call_estimates estimates
;
231 ctx
.estimate_size_and_time (&estimates
);
232 size
= estimates
.size
;
233 e
->entry
.size
= size
;
234 time
= estimates
.time
;
235 e
->entry
.time
= time
;
236 nonspec_time
= estimates
.nonspecialized_time
;
237 e
->entry
.nonspec_time
= nonspec_time
;
238 hints
= estimates
.hints
;
239 e
->entry
.hints
= hints
;
240 e
->entry
.ctx
.duplicate_from (ctx
);
245 ipa_call_estimates estimates
;
246 ctx
.estimate_size_and_time (&estimates
);
247 size
= estimates
.size
;
248 time
= estimates
.time
;
249 nonspec_time
= estimates
.nonspecialized_time
;
250 hints
= estimates
.hints
;
253 /* When we have profile feedback or function attribute, we can quite safely
254 identify hot edges and for those we disable size limits. Don't do that
255 when probability that caller will call the callee is low however, since it
256 may hurt optimization of the caller's hot path. */
257 if ((edge
->count
.ipa ().initialized_p () && edge
->maybe_hot_p ()
258 && (edge
->count
.ipa () * 2
259 > (edge
->caller
->inlined_to
260 ? edge
->caller
->inlined_to
->count
.ipa ()
261 : edge
->caller
->count
.ipa ())))
262 || (lookup_attribute ("hot", DECL_ATTRIBUTES (edge
->caller
->decl
))
264 && lookup_attribute ("hot", DECL_ATTRIBUTES (edge
->callee
->decl
))
266 hints
|= INLINE_HINT_known_hot
;
268 gcc_checking_assert (size
>= 0);
269 gcc_checking_assert (time
>= 0);
271 /* When caching, update the cache entry. */
272 if (edge_growth_cache
!= NULL
)
275 ipa_fn_summaries
->get (edge
->callee
->function_symbol ())->min_size
277 edge_growth_cache_entry
*entry
278 = edge_growth_cache
->get_create (edge
);
280 entry
->nonspec_time
= nonspec_time
;
282 entry
->size
= size
+ (size
>= 0);
283 hints
|= simple_edge_hints (edge
);
284 entry
->hints
= hints
+ 1;
286 if (ret_nonspec_time
)
287 *ret_nonspec_time
= nonspec_time
;
291 /* Reset cache for NODE.
292 This must be done each time NODE body is modified. */
294 reset_node_cache (struct cgraph_node
*node
)
296 if (node_context_cache
)
297 node_context_cache
->remove (node
);
300 /* Remove EDGE from caches once it was inlined. */
302 ipa_remove_from_growth_caches (struct cgraph_edge
*edge
)
304 if (node_context_cache
)
305 node_context_cache
->remove (edge
->callee
);
306 if (edge_growth_cache
)
307 edge_growth_cache
->remove (edge
);
310 /* Return estimated callee growth after inlining EDGE.
311 Only to be called via estimate_edge_size. */
314 do_estimate_edge_size (struct cgraph_edge
*edge
)
317 struct cgraph_node
*callee
;
318 clause_t clause
, nonspec_clause
;
320 /* When we do caching, use do_estimate_edge_time to populate the entry. */
322 if (edge_growth_cache
!= NULL
)
324 do_estimate_edge_time (edge
);
325 size
= edge_growth_cache
->get (edge
)->size
;
326 gcc_checking_assert (size
);
327 return size
- (size
> 0);
330 callee
= edge
->callee
->ultimate_alias_target ();
332 /* Early inliner runs without caching, go ahead and do the dirty work. */
333 gcc_checking_assert (edge
->inline_failed
);
334 ipa_auto_call_arg_values avals
;
335 evaluate_properties_for_edge (edge
, true, &clause
, &nonspec_clause
,
337 ipa_call_context
ctx (callee
, clause
, nonspec_clause
, vNULL
, &avals
);
338 ipa_call_estimates estimates
;
339 ctx
.estimate_size_and_time (&estimates
, false, false);
340 return estimates
.size
;
344 /* Estimate the growth of the caller when inlining EDGE.
345 Only to be called via estimate_edge_size. */
348 do_estimate_edge_hints (struct cgraph_edge
*edge
)
350 struct cgraph_node
*callee
;
351 clause_t clause
, nonspec_clause
;
353 /* When we do caching, use do_estimate_edge_time to populate the entry. */
355 if (edge_growth_cache
!= NULL
)
357 do_estimate_edge_time (edge
);
358 ipa_hints hints
= edge_growth_cache
->get (edge
)->hints
;
359 gcc_checking_assert (hints
);
363 callee
= edge
->callee
->ultimate_alias_target ();
365 /* Early inliner runs without caching, go ahead and do the dirty work. */
366 gcc_checking_assert (edge
->inline_failed
);
367 ipa_auto_call_arg_values avals
;
368 evaluate_properties_for_edge (edge
, true, &clause
, &nonspec_clause
,
370 ipa_call_context
ctx (callee
, clause
, nonspec_clause
, vNULL
, &avals
);
371 ipa_call_estimates estimates
;
372 ctx
.estimate_size_and_time (&estimates
, false, true);
373 ipa_hints hints
= estimates
.hints
| simple_edge_hints (edge
);
377 /* Estimate the size of NODE after inlining EDGE which should be an
378 edge to either NODE or a call inlined into NODE. */
381 estimate_size_after_inlining (struct cgraph_node
*node
,
382 struct cgraph_edge
*edge
)
384 class ipa_call_summary
*es
= ipa_call_summaries
->get (edge
);
385 ipa_size_summary
*s
= ipa_size_summaries
->get (node
);
386 if (!es
->predicate
|| *es
->predicate
!= false)
388 int size
= s
->size
+ estimate_edge_growth (edge
);
389 gcc_assert (size
>= 0);
398 struct cgraph_node
*node
;
406 /* Worker for do_estimate_growth. Collect growth for all callers. */
409 do_estimate_growth_1 (struct cgraph_node
*node
, void *data
)
411 struct cgraph_edge
*e
;
412 struct growth_data
*d
= (struct growth_data
*) data
;
414 for (e
= node
->callers
; e
; e
= e
->next_caller
)
416 gcc_checking_assert (e
->inline_failed
);
418 if (cgraph_inline_failed_type (e
->inline_failed
) == CIF_FINAL_ERROR
419 || !opt_for_fn (e
->caller
->decl
, optimize
))
421 d
->uninlinable
= true;
422 if (d
->cap
< INT_MAX
)
427 if (e
->recursive_p ())
429 d
->self_recursive
= true;
430 if (d
->cap
< INT_MAX
)
434 d
->growth
+= estimate_edge_growth (e
);
435 if (d
->growth
> d
->cap
)
441 /* Return estimated savings for eliminating offline copy of NODE by inlining
445 offline_size (struct cgraph_node
*node
, ipa_size_summary
*info
)
447 if (!DECL_EXTERNAL (node
->decl
))
449 if (node
->will_be_removed_from_program_if_no_direct_calls_p ())
451 /* COMDAT functions are very often not shared across multiple units
452 since they come from various template instantiations.
453 Take this into account. */
454 else if (DECL_COMDAT (node
->decl
)
455 && node
->can_remove_if_no_direct_calls_p ())
457 int prob
= opt_for_fn (node
->decl
, param_comdat_sharing_probability
);
458 return (info
->size
* (100 - prob
) + 50) / 100;
464 /* Estimate the growth caused by inlining NODE into all callers. */
467 estimate_growth (struct cgraph_node
*node
)
469 struct growth_data d
= { node
, false, false, 0, INT_MAX
};
470 ipa_size_summary
*info
= ipa_size_summaries
->get (node
);
472 if (node
->call_for_symbol_and_aliases (do_estimate_growth_1
, &d
, true))
475 /* For self recursive functions the growth estimation really should be
476 infinity. We don't want to return very large values because the growth
477 plays various roles in badness computation fractions. Be sure to not
478 return zero or negative growths. */
479 if (d
.self_recursive
)
480 d
.growth
= d
.growth
< info
->size
? info
->size
: d
.growth
;
481 else if (!d
.uninlinable
)
482 d
.growth
-= offline_size (node
, info
);
487 /* Verify if there are fewer than MAX_CALLERS. */
490 check_callers (cgraph_node
*node
, int *growth
, int *n
, int offline
,
491 int min_size
, struct cgraph_edge
*known_edge
)
495 if (!node
->can_remove_if_no_direct_calls_and_refs_p ())
498 for (cgraph_edge
*e
= node
->callers
; e
; e
= e
->next_caller
)
500 edge_growth_cache_entry
*entry
;
504 if (cgraph_inline_failed_type (e
->inline_failed
) == CIF_FINAL_ERROR
)
506 if (edge_growth_cache
!= NULL
507 && (entry
= edge_growth_cache
->get (e
)) != NULL
509 *growth
+= entry
->size
- (entry
->size
> 0);
512 class ipa_call_summary
*es
= ipa_call_summaries
->get (e
);
515 *growth
+= min_size
- es
->call_stmt_size
;
519 if (*growth
> offline
)
524 FOR_EACH_ALIAS (node
, ref
)
525 if (check_callers (dyn_cast
<cgraph_node
*> (ref
->referring
), growth
, n
,
526 offline
, min_size
, known_edge
))
533 /* Decide if growth of NODE is positive. This is cheaper than calculating
534 actual growth. If edge growth of KNOWN_EDGE is known
535 it is passed by EDGE_GROWTH. */
538 growth_positive_p (struct cgraph_node
*node
,
539 struct cgraph_edge
* known_edge
, int edge_growth
)
541 struct cgraph_edge
*e
;
543 ipa_size_summary
*s
= ipa_size_summaries
->get (node
);
545 /* First quickly check if NODE is removable at all. */
546 int offline
= offline_size (node
, s
);
547 if (offline
<= 0 && known_edge
&& edge_growth
> 0)
550 int min_size
= ipa_fn_summaries
->get (node
)->min_size
;
553 int min_growth
= known_edge
? edge_growth
: 0;
554 for (e
= node
->callers
; e
; e
= e
->next_caller
)
556 edge_growth_cache_entry
*entry
;
558 if (cgraph_inline_failed_type (e
->inline_failed
) == CIF_FINAL_ERROR
)
562 if (edge_growth_cache
!= NULL
563 && (entry
= edge_growth_cache
->get (e
)) != NULL
565 min_growth
+= entry
->size
- (entry
->size
> 0);
568 class ipa_call_summary
*es
= ipa_call_summaries
->get (e
);
571 min_growth
+= min_size
- es
->call_stmt_size
;
575 if (min_growth
> offline
)
581 FOR_EACH_ALIAS (node
, ref
)
582 if (check_callers (dyn_cast
<cgraph_node
*> (ref
->referring
),
583 &min_growth
, &n
, offline
, min_size
, known_edge
))
586 struct growth_data d
= { node
, false, false, 0, offline
};
587 if (node
->call_for_symbol_and_aliases (do_estimate_growth_1
, &d
, true))
589 if (d
.self_recursive
|| d
.uninlinable
)
591 return (d
.growth
> offline
);