Branch data Line data Source code
1 : : /* Analysis used by inlining decision heuristics.
2 : : Copyright (C) 2003-2024 Free Software Foundation, Inc.
3 : : Contributed by Jan Hubicka
4 : :
5 : : This file is part of GCC.
6 : :
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
10 : : version.
11 : :
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
15 : : for more details.
16 : :
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/>. */
20 : :
21 : : #include "config.h"
22 : : #include "system.h"
23 : : #include "coretypes.h"
24 : : #include "backend.h"
25 : : #include "tree.h"
26 : : #include "gimple.h"
27 : : #include "alloc-pool.h"
28 : : #include "tree-pass.h"
29 : : #include "ssa.h"
30 : : #include "tree-streamer.h"
31 : : #include "cgraph.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"
37 : : #include "cfganal.h"
38 : : #include "gimple-iterator.h"
39 : : #include "tree-cfg.h"
40 : : #include "tree-ssa-loop-niter.h"
41 : : #include "tree-ssa-loop.h"
42 : : #include "symbol-summary.h"
43 : : #include "sreal.h"
44 : : #include "ipa-cp.h"
45 : : #include "ipa-prop.h"
46 : : #include "ipa-fnsummary.h"
47 : : #include "ipa-inline.h"
48 : : #include "cfgloop.h"
49 : : #include "tree-scalar-evolution.h"
50 : : #include "ipa-utils.h"
51 : : #include "cfgexpand.h"
52 : : #include "gimplify.h"
53 : : #include "attribs.h"
54 : :
55 : : /* Cached node/edge growths. */
56 : : fast_call_summary<edge_growth_cache_entry *, va_heap> *edge_growth_cache = NULL;
57 : :
58 : : /* The context cache remembers estimated time/size and hints for given
59 : : ipa_call_context of a call. */
60 : : class node_context_cache_entry
61 : : {
62 : : public:
63 : : ipa_cached_call_context ctx;
64 : : sreal time, nonspec_time;
65 : : int size;
66 : : ipa_hints hints;
67 : :
68 : 1010853 : node_context_cache_entry ()
69 : 1010853 : : ctx ()
70 : : {
71 : : }
72 : 1010853 : ~node_context_cache_entry ()
73 : : {
74 : 1010853 : ctx.release ();
75 : : }
76 : : };
77 : :
78 : : /* At the moment we implement primitive single entry LRU cache. */
79 : : class node_context_summary
80 : : {
81 : : public:
82 : : node_context_cache_entry entry;
83 : :
84 : 1010853 : node_context_summary ()
85 : 0 : : entry ()
86 : : {
87 : : }
88 : 1010853 : ~node_context_summary ()
89 : : {
90 : 1010853 : }
91 : : };
92 : :
93 : : /* Summary holding the context cache. */
94 : : static fast_function_summary <node_context_summary *, va_heap>
95 : : *node_context_cache = NULL;
96 : : /* Statistics about the context cache effectivity. */
97 : : static long node_context_cache_hit, node_context_cache_miss,
98 : : node_context_cache_clear;
99 : :
100 : : /* Give initial reasons why inlining would fail on EDGE. This gets either
101 : : nullified or usually overwritten by more precise reasons later. */
102 : :
103 : : void
104 : 36601032 : initialize_inline_failed (struct cgraph_edge *e)
105 : : {
106 : 36601032 : struct cgraph_node *callee = e->callee;
107 : :
108 : 36601032 : if (e->inline_failed && e->inline_failed != CIF_BODY_NOT_AVAILABLE
109 : 72972222 : && cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR)
110 : : ;
111 : 36587707 : else if (e->indirect_unknown_callee)
112 : 655739 : e->inline_failed = CIF_INDIRECT_UNKNOWN_CALL;
113 : 35931968 : else if (!callee->definition)
114 : 19745574 : e->inline_failed = CIF_BODY_NOT_AVAILABLE;
115 : 16186394 : else if (callee->redefined_extern_inline)
116 : 178 : e->inline_failed = CIF_REDEFINED_EXTERN_INLINE;
117 : : else
118 : 16186216 : e->inline_failed = CIF_FUNCTION_NOT_CONSIDERED;
119 : 36601032 : gcc_checking_assert (!e->call_stmt_cannot_inline_p
120 : : || cgraph_inline_failed_type (e->inline_failed)
121 : : == CIF_FINAL_ERROR);
122 : 36601032 : }
123 : :
124 : : /* Allocate edge growth caches. */
125 : :
126 : : void
127 : 225138 : initialize_growth_caches ()
128 : : {
129 : 225138 : edge_growth_cache
130 : 225138 : = new fast_call_summary<edge_growth_cache_entry *, va_heap> (symtab);
131 : 225138 : node_context_cache
132 : 225138 : = new fast_function_summary<node_context_summary *, va_heap> (symtab);
133 : 225138 : edge_growth_cache->disable_duplication_hook ();
134 : 225138 : node_context_cache->disable_insertion_hook ();
135 : 225138 : node_context_cache->disable_duplication_hook ();
136 : 225138 : }
137 : :
138 : : /* Free growth caches. */
139 : :
140 : : void
141 : 225138 : free_growth_caches (void)
142 : : {
143 : 225138 : delete edge_growth_cache;
144 : 225138 : delete node_context_cache;
145 : 225138 : edge_growth_cache = NULL;
146 : 225138 : node_context_cache = NULL;
147 : 225138 : if (dump_file)
148 : 178 : fprintf (dump_file, "node context cache: %li hits, %li misses,"
149 : : " %li initializations\n",
150 : : node_context_cache_hit, node_context_cache_miss,
151 : : node_context_cache_clear);
152 : 225138 : node_context_cache_hit = 0;
153 : 225138 : node_context_cache_miss = 0;
154 : 225138 : node_context_cache_clear = 0;
155 : 225138 : }
156 : :
157 : : /* Return hints derived from EDGE. */
158 : :
159 : : int
160 : 5485124 : simple_edge_hints (struct cgraph_edge *edge)
161 : : {
162 : 5485124 : int hints = 0;
163 : 10970248 : struct cgraph_node *to = (edge->caller->inlined_to
164 : 5485124 : ? edge->caller->inlined_to : edge->caller);
165 : 5485124 : struct cgraph_node *callee = edge->callee->ultimate_alias_target ();
166 : 5485124 : int to_scc_no = ipa_fn_summaries->get (to)->scc_no;
167 : 5485124 : int callee_scc_no = ipa_fn_summaries->get (callee)->scc_no;
168 : :
169 : 5485124 : if (to_scc_no && to_scc_no == callee_scc_no && !edge->recursive_p ())
170 : : hints |= INLINE_HINT_same_scc;
171 : :
172 : 5485124 : if (cross_module_call_p (edge))
173 : 4035 : hints |= INLINE_HINT_cross_module;
174 : :
175 : 5485124 : return hints;
176 : : }
177 : :
178 : : /* Estimate the time cost for the caller when inlining EDGE.
179 : : Only to be called via estimate_edge_time, that handles the
180 : : caching mechanism.
181 : :
182 : : When caching, also update the cache entry. Compute both time and
183 : : size, since we always need both metrics eventually. */
184 : :
185 : : sreal
186 : 5488936 : do_estimate_edge_time (struct cgraph_edge *edge, sreal *ret_nonspec_time)
187 : : {
188 : 5488936 : sreal time, nonspec_time;
189 : 5488936 : int size;
190 : 5488936 : ipa_hints hints;
191 : 5488936 : struct cgraph_node *callee;
192 : 5488936 : clause_t clause, nonspec_clause;
193 : 5488936 : ipa_auto_call_arg_values avals;
194 : 5488936 : class ipa_call_summary *es = ipa_call_summaries->get (edge);
195 : 5488936 : int min_size = -1;
196 : :
197 : 5488936 : callee = edge->callee->ultimate_alias_target ();
198 : :
199 : 5488936 : gcc_checking_assert (edge->inline_failed);
200 : 5488936 : evaluate_properties_for_edge (edge, true, &clause, &nonspec_clause,
201 : : &avals, true);
202 : 5488936 : ipa_call_context ctx (callee, clause, nonspec_clause, es->param, &avals);
203 : 5488936 : if (node_context_cache != NULL)
204 : : {
205 : 5485124 : node_context_summary *e = node_context_cache->get_create (callee);
206 : 5485124 : if (e->entry.ctx.equal_to (ctx))
207 : : {
208 : 3861122 : node_context_cache_hit++;
209 : 3861122 : size = e->entry.size;
210 : 3861122 : time = e->entry.time;
211 : 3861122 : nonspec_time = e->entry.nonspec_time;
212 : 3861122 : hints = e->entry.hints;
213 : 3861122 : if (flag_checking
214 : 3861122 : && !opt_for_fn (callee->decl, flag_profile_partial_training)
215 : 7722244 : && !callee->count.ipa_p ())
216 : : {
217 : 3827223 : ipa_call_estimates chk_estimates;
218 : 3827223 : ctx.estimate_size_and_time (&chk_estimates);
219 : 11481669 : gcc_assert (chk_estimates.size == size
220 : : && chk_estimates.time == time
221 : : && chk_estimates.nonspecialized_time == nonspec_time
222 : : && chk_estimates.hints == hints);
223 : : }
224 : : }
225 : : else
226 : : {
227 : 1624002 : if (e->entry.ctx.exists_p ())
228 : 613149 : node_context_cache_miss++;
229 : : else
230 : 1010853 : node_context_cache_clear++;
231 : 1624002 : e->entry.ctx.release ();
232 : 1624002 : ipa_call_estimates estimates;
233 : 1624002 : ctx.estimate_size_and_time (&estimates);
234 : 1624002 : size = estimates.size;
235 : 1624002 : e->entry.size = size;
236 : 1624002 : time = estimates.time;
237 : 1624002 : e->entry.time = time;
238 : 1624002 : nonspec_time = estimates.nonspecialized_time;
239 : 1624002 : e->entry.nonspec_time = nonspec_time;
240 : 1624002 : hints = estimates.hints;
241 : 1624002 : e->entry.hints = hints;
242 : 1624002 : e->entry.ctx.duplicate_from (ctx);
243 : : }
244 : : }
245 : : else
246 : : {
247 : 3812 : ipa_call_estimates estimates;
248 : 3812 : ctx.estimate_size_and_time (&estimates);
249 : 3812 : size = estimates.size;
250 : 3812 : time = estimates.time;
251 : 3812 : nonspec_time = estimates.nonspecialized_time;
252 : 3812 : hints = estimates.hints;
253 : : }
254 : :
255 : : /* When we have profile feedback or function attribute, we can quite safely
256 : : identify hot edges and for those we disable size limits. Don't do that
257 : : when probability that caller will call the callee is low however, since it
258 : : may hurt optimization of the caller's hot path. */
259 : 5488936 : if ((edge->count.ipa ().initialized_p () && edge->maybe_hot_p ()
260 : 254 : && (edge->count.ipa () * 2
261 : 127 : > (edge->caller->inlined_to
262 : 5488949 : ? edge->caller->inlined_to->count.ipa ()
263 : 100 : : edge->caller->count.ipa ())))
264 : 5754790 : || (lookup_attribute ("hot", DECL_ATTRIBUTES (edge->caller->decl))
265 : : != NULL
266 : 2 : && lookup_attribute ("hot", DECL_ATTRIBUTES (edge->callee->decl))
267 : : != NULL))
268 : 114 : hints |= INLINE_HINT_known_hot;
269 : :
270 : 5488936 : gcc_checking_assert (size >= 0);
271 : 5488936 : gcc_checking_assert (time >= 0);
272 : :
273 : : /* When caching, update the cache entry. */
274 : 5488936 : if (edge_growth_cache != NULL)
275 : : {
276 : 5485124 : if (min_size >= 0)
277 : : ipa_fn_summaries->get (edge->callee->function_symbol ())->min_size
278 : : = min_size;
279 : 5485124 : edge_growth_cache_entry *entry
280 : 5485124 : = edge_growth_cache->get_create (edge);
281 : 5485124 : entry->time = time;
282 : 5485124 : entry->nonspec_time = nonspec_time;
283 : :
284 : 5485124 : entry->size = size + (size >= 0);
285 : 5485124 : hints |= simple_edge_hints (edge);
286 : 5485124 : entry->hints = hints + 1;
287 : : }
288 : 5488936 : if (ret_nonspec_time)
289 : 86467 : *ret_nonspec_time = nonspec_time;
290 : 10977872 : return time;
291 : 5488936 : }
292 : :
293 : : /* Reset cache for NODE.
294 : : This must be done each time NODE body is modified. */
295 : : void
296 : 2707283 : reset_node_cache (struct cgraph_node *node)
297 : : {
298 : 2707283 : if (node_context_cache)
299 : 2707203 : node_context_cache->remove (node);
300 : 2707283 : }
301 : :
302 : : /* Remove EDGE from caches once it was inlined. */
303 : : void
304 : 3339302 : ipa_remove_from_growth_caches (struct cgraph_edge *edge)
305 : : {
306 : 3339302 : if (node_context_cache)
307 : 752287 : node_context_cache->remove (edge->callee);
308 : 3339302 : if (edge_growth_cache)
309 : 752287 : edge_growth_cache->remove (edge);
310 : 3339302 : }
311 : :
312 : : /* Return estimated callee growth after inlining EDGE.
313 : : Only to be called via estimate_edge_size. */
314 : :
315 : : int
316 : 15832326 : do_estimate_edge_size (struct cgraph_edge *edge)
317 : : {
318 : 15832326 : int size;
319 : 15832326 : struct cgraph_node *callee;
320 : 15832326 : clause_t clause, nonspec_clause;
321 : :
322 : : /* When we do caching, use do_estimate_edge_time to populate the entry. */
323 : :
324 : 15832326 : if (edge_growth_cache != NULL)
325 : : {
326 : 5361015 : do_estimate_edge_time (edge);
327 : 5361015 : size = edge_growth_cache->get (edge)->size;
328 : 5361015 : gcc_checking_assert (size);
329 : 5361015 : return size - (size > 0);
330 : : }
331 : :
332 : 10471311 : callee = edge->callee->ultimate_alias_target ();
333 : :
334 : : /* Early inliner runs without caching, go ahead and do the dirty work. */
335 : 10471311 : gcc_checking_assert (edge->inline_failed);
336 : 10471311 : ipa_auto_call_arg_values avals;
337 : 10471311 : evaluate_properties_for_edge (edge, true, &clause, &nonspec_clause,
338 : : &avals, true);
339 : 10471311 : ipa_call_context ctx (callee, clause, nonspec_clause, vNULL, &avals);
340 : 10471311 : ipa_call_estimates estimates;
341 : 10471311 : ctx.estimate_size_and_time (&estimates, false, false);
342 : 10471311 : return estimates.size;
343 : 10471311 : }
344 : :
345 : :
346 : : /* Estimate the growth of the caller when inlining EDGE.
347 : : Only to be called via estimate_edge_size. */
348 : :
349 : : ipa_hints
350 : 0 : do_estimate_edge_hints (struct cgraph_edge *edge)
351 : : {
352 : 0 : struct cgraph_node *callee;
353 : 0 : clause_t clause, nonspec_clause;
354 : :
355 : : /* When we do caching, use do_estimate_edge_time to populate the entry. */
356 : :
357 : 0 : if (edge_growth_cache != NULL)
358 : : {
359 : 0 : do_estimate_edge_time (edge);
360 : 0 : ipa_hints hints = edge_growth_cache->get (edge)->hints;
361 : 0 : gcc_checking_assert (hints);
362 : 0 : return hints - 1;
363 : : }
364 : :
365 : 0 : callee = edge->callee->ultimate_alias_target ();
366 : :
367 : : /* Early inliner runs without caching, go ahead and do the dirty work. */
368 : 0 : gcc_checking_assert (edge->inline_failed);
369 : 0 : ipa_auto_call_arg_values avals;
370 : 0 : evaluate_properties_for_edge (edge, true, &clause, &nonspec_clause,
371 : : &avals, true);
372 : 0 : ipa_call_context ctx (callee, clause, nonspec_clause, vNULL, &avals);
373 : 0 : ipa_call_estimates estimates;
374 : 0 : ctx.estimate_size_and_time (&estimates, false, true);
375 : 0 : ipa_hints hints = estimates.hints | simple_edge_hints (edge);
376 : 0 : return hints;
377 : 0 : }
378 : :
379 : : /* Estimate the size of NODE after inlining EDGE which should be an
380 : : edge to either NODE or a call inlined into NODE. */
381 : :
382 : : int
383 : 5504052 : estimate_size_after_inlining (struct cgraph_node *node,
384 : : struct cgraph_edge *edge)
385 : : {
386 : 5504052 : class ipa_call_summary *es = ipa_call_summaries->get (edge);
387 : 5504052 : ipa_size_summary *s = ipa_size_summaries->get (node);
388 : 5504052 : if (!es->predicate || *es->predicate != false)
389 : : {
390 : 5504052 : int size = s->size + estimate_edge_growth (edge);
391 : 5504052 : gcc_assert (size >= 0);
392 : : return size;
393 : : }
394 : 0 : return s->size;
395 : : }
396 : :
397 : :
398 : : struct growth_data
399 : : {
400 : : struct cgraph_node *node;
401 : : bool self_recursive;
402 : : bool uninlinable;
403 : : int growth;
404 : : int cap;
405 : : };
406 : :
407 : :
408 : : /* Worker for do_estimate_growth. Collect growth for all callers. */
409 : :
410 : : static bool
411 : 1723725 : do_estimate_growth_1 (struct cgraph_node *node, void *data)
412 : : {
413 : 1723725 : struct cgraph_edge *e;
414 : 1723725 : struct growth_data *d = (struct growth_data *) data;
415 : :
416 : 3850233 : for (e = node->callers; e; e = e->next_caller)
417 : : {
418 : 2213779 : gcc_checking_assert (e->inline_failed);
419 : :
420 : 2213779 : if (cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR
421 : 2213779 : || !opt_for_fn (e->caller->decl, optimize))
422 : : {
423 : 288 : d->uninlinable = true;
424 : 288 : if (d->cap < INT_MAX)
425 : : return true;
426 : 288 : continue;
427 : : }
428 : :
429 : 2213491 : if (e->recursive_p ())
430 : : {
431 : 9664 : d->self_recursive = true;
432 : 9664 : if (d->cap < INT_MAX)
433 : : return true;
434 : 8336 : continue;
435 : : }
436 : 2203827 : d->growth += estimate_edge_growth (e);
437 : 2203827 : if (d->growth > d->cap)
438 : : return true;
439 : : }
440 : : return false;
441 : : }
442 : :
443 : : /* Return estimated savings for eliminating offline copy of NODE by inlining
444 : : it everywhere. */
445 : :
446 : : static int
447 : 3275540 : offline_size (struct cgraph_node *node, ipa_size_summary *info)
448 : : {
449 : 3275540 : if (!DECL_EXTERNAL (node->decl))
450 : : {
451 : 3156011 : if (node->will_be_removed_from_program_if_no_direct_calls_p ())
452 : 966320 : return info->size;
453 : : /* COMDAT functions are very often not shared across multiple units
454 : : since they come from various template instantiations.
455 : : Take this into account. */
456 : 2189691 : else if (DECL_COMDAT (node->decl)
457 : 2189691 : && node->can_remove_if_no_direct_calls_p ())
458 : : {
459 : 538001 : int prob = opt_for_fn (node->decl, param_comdat_sharing_probability);
460 : 538001 : return (info->size * (100 - prob) + 50) / 100;
461 : : }
462 : : }
463 : : return 0;
464 : : }
465 : :
466 : : /* Estimate the growth caused by inlining NODE into all callers. */
467 : :
468 : : int
469 : 1329566 : estimate_growth (struct cgraph_node *node)
470 : : {
471 : 1329566 : struct growth_data d = { node, false, false, 0, INT_MAX };
472 : 1329566 : ipa_size_summary *info = ipa_size_summaries->get (node);
473 : :
474 : 1329566 : if (node->call_for_symbol_and_aliases (do_estimate_growth_1, &d, true))
475 : : return 1;
476 : :
477 : : /* For self recursive functions the growth estimation really should be
478 : : infinity. We don't want to return very large values because the growth
479 : : plays various roles in badness computation fractions. Be sure to not
480 : : return zero or negative growths. */
481 : 1329566 : if (d.self_recursive)
482 : 4144 : d.growth = d.growth < info->size ? info->size : d.growth;
483 : 1325422 : else if (!d.uninlinable)
484 : 1325231 : d.growth -= offline_size (node, info);
485 : :
486 : 1329566 : return d.growth;
487 : : }
488 : :
489 : : /* Verify if there are fewer than MAX_CALLERS. */
490 : :
491 : : static bool
492 : 103784 : check_callers (cgraph_node *node, int *growth, int *n, int offline,
493 : : int min_size, struct cgraph_edge *known_edge)
494 : : {
495 : 103784 : ipa_ref *ref;
496 : :
497 : 103784 : if (!node->can_remove_if_no_direct_calls_and_refs_p ())
498 : : return true;
499 : :
500 : 160606 : for (cgraph_edge *e = node->callers; e; e = e->next_caller)
501 : : {
502 : 132902 : edge_growth_cache_entry *entry;
503 : :
504 : 132902 : if (e == known_edge)
505 : 26593 : continue;
506 : 106309 : if (cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR)
507 : : return true;
508 : 103652 : if (edge_growth_cache != NULL
509 : 77994 : && (entry = edge_growth_cache->get (e)) != NULL
510 : 163075 : && entry->size != 0)
511 : 59423 : *growth += entry->size - (entry->size > 0);
512 : : else
513 : : {
514 : 44229 : class ipa_call_summary *es = ipa_call_summaries->get (e);
515 : 44229 : if (!es)
516 : : return true;
517 : 44225 : *growth += min_size - es->call_stmt_size;
518 : 44225 : if (--(*n) < 0)
519 : : return false;
520 : : }
521 : 103358 : if (*growth > offline)
522 : : return true;
523 : : }
524 : :
525 : 27704 : if (*n > 0)
526 : 27692 : FOR_EACH_ALIAS (node, ref)
527 : 68 : if (check_callers (dyn_cast <cgraph_node *> (ref->referring), growth, n,
528 : : offline, min_size, known_edge))
529 : : return true;
530 : :
531 : : return false;
532 : : }
533 : :
534 : :
535 : : /* Decide if growth of NODE is positive. This is cheaper than calculating
536 : : actual growth. If edge growth of KNOWN_EDGE is known
537 : : it is passed by EDGE_GROWTH. */
538 : :
539 : : bool
540 : 1950309 : growth_positive_p (struct cgraph_node *node,
541 : : struct cgraph_edge * known_edge, int edge_growth)
542 : : {
543 : 1950309 : struct cgraph_edge *e;
544 : :
545 : 1950309 : ipa_size_summary *s = ipa_size_summaries->get (node);
546 : :
547 : : /* First quickly check if NODE is removable at all. */
548 : 1950309 : int offline = offline_size (node, s);
549 : 1950309 : if (offline <= 0 && known_edge && edge_growth > 0)
550 : : return true;
551 : :
552 : 1464785 : int min_size = ipa_fn_summaries->get (node)->min_size;
553 : 1464785 : int n = 10;
554 : :
555 : 1464785 : int min_growth = known_edge ? edge_growth : 0;
556 : 2390201 : for (e = node->callers; e; e = e->next_caller)
557 : : {
558 : 2022937 : edge_growth_cache_entry *entry;
559 : :
560 : 2022937 : if (cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR)
561 : : return true;
562 : 1601971 : if (e == known_edge)
563 : 258092 : continue;
564 : 1343879 : if (edge_growth_cache != NULL
565 : 807240 : && (entry = edge_growth_cache->get (e)) != NULL
566 : 2041205 : && entry->size != 0)
567 : 697326 : min_growth += entry->size - (entry->size > 0);
568 : : else
569 : : {
570 : 646553 : class ipa_call_summary *es = ipa_call_summaries->get (e);
571 : 646553 : if (!es)
572 : : return true;
573 : 646420 : min_growth += min_size - es->call_stmt_size;
574 : 646420 : if (--n <= 0)
575 : : break;
576 : : }
577 : 1334080 : if (min_growth > offline)
578 : : return true;
579 : : }
580 : :
581 : 376930 : ipa_ref *ref;
582 : 376930 : if (n > 0)
583 : 395224 : FOR_EACH_ALIAS (node, ref)
584 : 207500 : if (check_callers (dyn_cast <cgraph_node *> (ref->referring),
585 : : &min_growth, &n, offline, min_size, known_edge))
586 : : return true;
587 : :
588 : 301140 : struct growth_data d = { node, false, false, 0, offline };
589 : 301140 : if (node->call_for_symbol_and_aliases (do_estimate_growth_1, &d, true))
590 : : return true;
591 : 213869 : if (d.self_recursive || d.uninlinable)
592 : : return true;
593 : 213869 : return (d.growth > offline);
594 : : }
|