Mercurial > hg > CbC > CbC_gcc
comparison gcc/ipa-inline-analysis.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* Analysis used by inlining decision heuristics. | |
2 Copyright (C) 2003-2017 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 "params.h" | |
38 #include "cfganal.h" | |
39 #include "gimple-iterator.h" | |
40 #include "tree-cfg.h" | |
41 #include "tree-ssa-loop-niter.h" | |
42 #include "tree-ssa-loop.h" | |
43 #include "symbol-summary.h" | |
44 #include "ipa-prop.h" | |
45 #include "ipa-fnsummary.h" | |
46 #include "ipa-inline.h" | |
47 #include "cfgloop.h" | |
48 #include "tree-scalar-evolution.h" | |
49 #include "ipa-utils.h" | |
50 #include "cilk.h" | |
51 #include "cfgexpand.h" | |
52 #include "gimplify.h" | |
53 | |
54 /* Cached node/edge growths. */ | |
55 vec<edge_growth_cache_entry> edge_growth_cache; | |
56 static struct cgraph_edge_hook_list *edge_removal_hook_holder; | |
57 | |
58 | |
59 /* Give initial reasons why inlining would fail on EDGE. This gets either | |
60 nullified or usually overwritten by more precise reasons later. */ | |
61 | |
62 void | |
63 initialize_inline_failed (struct cgraph_edge *e) | |
64 { | |
65 struct cgraph_node *callee = e->callee; | |
66 | |
67 if (e->inline_failed && e->inline_failed != CIF_BODY_NOT_AVAILABLE | |
68 && cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR) | |
69 ; | |
70 else if (e->indirect_unknown_callee) | |
71 e->inline_failed = CIF_INDIRECT_UNKNOWN_CALL; | |
72 else if (!callee->definition) | |
73 e->inline_failed = CIF_BODY_NOT_AVAILABLE; | |
74 else if (callee->local.redefined_extern_inline) | |
75 e->inline_failed = CIF_REDEFINED_EXTERN_INLINE; | |
76 else | |
77 e->inline_failed = CIF_FUNCTION_NOT_CONSIDERED; | |
78 gcc_checking_assert (!e->call_stmt_cannot_inline_p | |
79 || cgraph_inline_failed_type (e->inline_failed) | |
80 == CIF_FINAL_ERROR); | |
81 } | |
82 | |
83 | |
84 /* Keep edge cache consistent across edge removal. */ | |
85 | |
86 static void | |
87 inline_edge_removal_hook (struct cgraph_edge *edge, | |
88 void *data ATTRIBUTE_UNUSED) | |
89 { | |
90 reset_edge_growth_cache (edge); | |
91 } | |
92 | |
93 | |
94 /* Initialize growth caches. */ | |
95 | |
96 void | |
97 initialize_growth_caches (void) | |
98 { | |
99 if (!edge_removal_hook_holder) | |
100 edge_removal_hook_holder = | |
101 symtab->add_edge_removal_hook (&inline_edge_removal_hook, NULL); | |
102 if (symtab->edges_max_uid) | |
103 edge_growth_cache.safe_grow_cleared (symtab->edges_max_uid); | |
104 } | |
105 | |
106 | |
107 /* Free growth caches. */ | |
108 | |
109 void | |
110 free_growth_caches (void) | |
111 { | |
112 if (edge_removal_hook_holder) | |
113 { | |
114 symtab->remove_edge_removal_hook (edge_removal_hook_holder); | |
115 edge_removal_hook_holder = NULL; | |
116 } | |
117 edge_growth_cache.release (); | |
118 } | |
119 | |
120 /* Return hints derrived from EDGE. */ | |
121 | |
122 int | |
123 simple_edge_hints (struct cgraph_edge *edge) | |
124 { | |
125 int hints = 0; | |
126 struct cgraph_node *to = (edge->caller->global.inlined_to | |
127 ? edge->caller->global.inlined_to : edge->caller); | |
128 struct cgraph_node *callee = edge->callee->ultimate_alias_target (); | |
129 if (ipa_fn_summaries->get (to)->scc_no | |
130 && ipa_fn_summaries->get (to)->scc_no | |
131 == ipa_fn_summaries->get (callee)->scc_no | |
132 && !edge->recursive_p ()) | |
133 hints |= INLINE_HINT_same_scc; | |
134 | |
135 if (callee->lto_file_data && edge->caller->lto_file_data | |
136 && edge->caller->lto_file_data != callee->lto_file_data | |
137 && !callee->merged_comdat && !callee->icf_merged) | |
138 hints |= INLINE_HINT_cross_module; | |
139 | |
140 return hints; | |
141 } | |
142 | |
143 /* Estimate the time cost for the caller when inlining EDGE. | |
144 Only to be called via estimate_edge_time, that handles the | |
145 caching mechanism. | |
146 | |
147 When caching, also update the cache entry. Compute both time and | |
148 size, since we always need both metrics eventually. */ | |
149 | |
150 sreal | |
151 do_estimate_edge_time (struct cgraph_edge *edge) | |
152 { | |
153 sreal time, nonspec_time; | |
154 int size; | |
155 ipa_hints hints; | |
156 struct cgraph_node *callee; | |
157 clause_t clause, nonspec_clause; | |
158 vec<tree> known_vals; | |
159 vec<ipa_polymorphic_call_context> known_contexts; | |
160 vec<ipa_agg_jump_function_p> known_aggs; | |
161 struct ipa_call_summary *es = ipa_call_summaries->get (edge); | |
162 int min_size; | |
163 | |
164 callee = edge->callee->ultimate_alias_target (); | |
165 | |
166 gcc_checking_assert (edge->inline_failed); | |
167 evaluate_properties_for_edge (edge, true, | |
168 &clause, &nonspec_clause, &known_vals, | |
169 &known_contexts, &known_aggs); | |
170 estimate_node_size_and_time (callee, clause, nonspec_clause, known_vals, | |
171 known_contexts, known_aggs, &size, &min_size, | |
172 &time, &nonspec_time, &hints, es->param); | |
173 | |
174 /* When we have profile feedback, we can quite safely identify hot | |
175 edges and for those we disable size limits. Don't do that when | |
176 probability that caller will call the callee is low however, since it | |
177 may hurt optimization of the caller's hot path. */ | |
178 if (edge->count.initialized_p () && edge->maybe_hot_p () | |
179 && (edge->count.apply_scale (2, 1) | |
180 > (edge->caller->global.inlined_to | |
181 ? edge->caller->global.inlined_to->count | |
182 : edge->caller->count))) | |
183 hints |= INLINE_HINT_known_hot; | |
184 | |
185 known_vals.release (); | |
186 known_contexts.release (); | |
187 known_aggs.release (); | |
188 gcc_checking_assert (size >= 0); | |
189 gcc_checking_assert (time >= 0); | |
190 | |
191 /* When caching, update the cache entry. */ | |
192 if (edge_growth_cache.exists ()) | |
193 { | |
194 ipa_fn_summaries->get (edge->callee)->min_size = min_size; | |
195 if ((int) edge_growth_cache.length () <= edge->uid) | |
196 edge_growth_cache.safe_grow_cleared (symtab->edges_max_uid); | |
197 edge_growth_cache[edge->uid].time = time; | |
198 edge_growth_cache[edge->uid].nonspec_time = nonspec_time; | |
199 | |
200 edge_growth_cache[edge->uid].size = size + (size >= 0); | |
201 hints |= simple_edge_hints (edge); | |
202 edge_growth_cache[edge->uid].hints = hints + 1; | |
203 } | |
204 return time; | |
205 } | |
206 | |
207 | |
208 /* Return estimated callee growth after inlining EDGE. | |
209 Only to be called via estimate_edge_size. */ | |
210 | |
211 int | |
212 do_estimate_edge_size (struct cgraph_edge *edge) | |
213 { | |
214 int size; | |
215 struct cgraph_node *callee; | |
216 clause_t clause, nonspec_clause; | |
217 vec<tree> known_vals; | |
218 vec<ipa_polymorphic_call_context> known_contexts; | |
219 vec<ipa_agg_jump_function_p> known_aggs; | |
220 | |
221 /* When we do caching, use do_estimate_edge_time to populate the entry. */ | |
222 | |
223 if (edge_growth_cache.exists ()) | |
224 { | |
225 do_estimate_edge_time (edge); | |
226 size = edge_growth_cache[edge->uid].size; | |
227 gcc_checking_assert (size); | |
228 return size - (size > 0); | |
229 } | |
230 | |
231 callee = edge->callee->ultimate_alias_target (); | |
232 | |
233 /* Early inliner runs without caching, go ahead and do the dirty work. */ | |
234 gcc_checking_assert (edge->inline_failed); | |
235 evaluate_properties_for_edge (edge, true, | |
236 &clause, &nonspec_clause, | |
237 &known_vals, &known_contexts, | |
238 &known_aggs); | |
239 estimate_node_size_and_time (callee, clause, nonspec_clause, known_vals, | |
240 known_contexts, known_aggs, &size, NULL, NULL, | |
241 NULL, NULL, vNULL); | |
242 known_vals.release (); | |
243 known_contexts.release (); | |
244 known_aggs.release (); | |
245 return size; | |
246 } | |
247 | |
248 | |
249 /* Estimate the growth of the caller when inlining EDGE. | |
250 Only to be called via estimate_edge_size. */ | |
251 | |
252 ipa_hints | |
253 do_estimate_edge_hints (struct cgraph_edge *edge) | |
254 { | |
255 ipa_hints hints; | |
256 struct cgraph_node *callee; | |
257 clause_t clause, nonspec_clause; | |
258 vec<tree> known_vals; | |
259 vec<ipa_polymorphic_call_context> known_contexts; | |
260 vec<ipa_agg_jump_function_p> known_aggs; | |
261 | |
262 /* When we do caching, use do_estimate_edge_time to populate the entry. */ | |
263 | |
264 if (edge_growth_cache.exists ()) | |
265 { | |
266 do_estimate_edge_time (edge); | |
267 hints = edge_growth_cache[edge->uid].hints; | |
268 gcc_checking_assert (hints); | |
269 return hints - 1; | |
270 } | |
271 | |
272 callee = edge->callee->ultimate_alias_target (); | |
273 | |
274 /* Early inliner runs without caching, go ahead and do the dirty work. */ | |
275 gcc_checking_assert (edge->inline_failed); | |
276 evaluate_properties_for_edge (edge, true, | |
277 &clause, &nonspec_clause, | |
278 &known_vals, &known_contexts, | |
279 &known_aggs); | |
280 estimate_node_size_and_time (callee, clause, nonspec_clause, known_vals, | |
281 known_contexts, known_aggs, NULL, NULL, | |
282 NULL, NULL, &hints, vNULL); | |
283 known_vals.release (); | |
284 known_contexts.release (); | |
285 known_aggs.release (); | |
286 hints |= simple_edge_hints (edge); | |
287 return hints; | |
288 } | |
289 | |
290 /* Estimate the size of NODE after inlining EDGE which should be an | |
291 edge to either NODE or a call inlined into NODE. */ | |
292 | |
293 int | |
294 estimate_size_after_inlining (struct cgraph_node *node, | |
295 struct cgraph_edge *edge) | |
296 { | |
297 struct ipa_call_summary *es = ipa_call_summaries->get (edge); | |
298 if (!es->predicate || *es->predicate != false) | |
299 { | |
300 int size = ipa_fn_summaries->get (node)->size + estimate_edge_growth (edge); | |
301 gcc_assert (size >= 0); | |
302 return size; | |
303 } | |
304 return ipa_fn_summaries->get (node)->size; | |
305 } | |
306 | |
307 | |
308 struct growth_data | |
309 { | |
310 struct cgraph_node *node; | |
311 bool self_recursive; | |
312 bool uninlinable; | |
313 int growth; | |
314 }; | |
315 | |
316 | |
317 /* Worker for do_estimate_growth. Collect growth for all callers. */ | |
318 | |
319 static bool | |
320 do_estimate_growth_1 (struct cgraph_node *node, void *data) | |
321 { | |
322 struct cgraph_edge *e; | |
323 struct growth_data *d = (struct growth_data *) data; | |
324 | |
325 for (e = node->callers; e; e = e->next_caller) | |
326 { | |
327 gcc_checking_assert (e->inline_failed); | |
328 | |
329 if (cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR | |
330 || !opt_for_fn (e->caller->decl, optimize)) | |
331 { | |
332 d->uninlinable = true; | |
333 continue; | |
334 } | |
335 | |
336 if (e->recursive_p ()) | |
337 { | |
338 d->self_recursive = true; | |
339 continue; | |
340 } | |
341 d->growth += estimate_edge_growth (e); | |
342 } | |
343 return false; | |
344 } | |
345 | |
346 | |
347 /* Estimate the growth caused by inlining NODE into all callees. */ | |
348 | |
349 int | |
350 estimate_growth (struct cgraph_node *node) | |
351 { | |
352 struct growth_data d = { node, false, false, 0 }; | |
353 struct ipa_fn_summary *info = ipa_fn_summaries->get (node); | |
354 | |
355 node->call_for_symbol_and_aliases (do_estimate_growth_1, &d, true); | |
356 | |
357 /* For self recursive functions the growth estimation really should be | |
358 infinity. We don't want to return very large values because the growth | |
359 plays various roles in badness computation fractions. Be sure to not | |
360 return zero or negative growths. */ | |
361 if (d.self_recursive) | |
362 d.growth = d.growth < info->size ? info->size : d.growth; | |
363 else if (DECL_EXTERNAL (node->decl) || d.uninlinable) | |
364 ; | |
365 else | |
366 { | |
367 if (node->will_be_removed_from_program_if_no_direct_calls_p ()) | |
368 d.growth -= info->size; | |
369 /* COMDAT functions are very often not shared across multiple units | |
370 since they come from various template instantiations. | |
371 Take this into account. */ | |
372 else if (DECL_COMDAT (node->decl) | |
373 && node->can_remove_if_no_direct_calls_p ()) | |
374 d.growth -= (info->size | |
375 * (100 - PARAM_VALUE (PARAM_COMDAT_SHARING_PROBABILITY)) | |
376 + 50) / 100; | |
377 } | |
378 | |
379 return d.growth; | |
380 } | |
381 | |
382 /* Verify if there are fewer than MAX_CALLERS. */ | |
383 | |
384 static bool | |
385 check_callers (cgraph_node *node, int *max_callers) | |
386 { | |
387 ipa_ref *ref; | |
388 | |
389 if (!node->can_remove_if_no_direct_calls_and_refs_p ()) | |
390 return true; | |
391 | |
392 for (cgraph_edge *e = node->callers; e; e = e->next_caller) | |
393 { | |
394 (*max_callers)--; | |
395 if (!*max_callers | |
396 || cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR) | |
397 return true; | |
398 } | |
399 | |
400 FOR_EACH_ALIAS (node, ref) | |
401 if (check_callers (dyn_cast <cgraph_node *> (ref->referring), max_callers)) | |
402 return true; | |
403 | |
404 return false; | |
405 } | |
406 | |
407 | |
408 /* Make cheap estimation if growth of NODE is likely positive knowing | |
409 EDGE_GROWTH of one particular edge. | |
410 We assume that most of other edges will have similar growth | |
411 and skip computation if there are too many callers. */ | |
412 | |
413 bool | |
414 growth_likely_positive (struct cgraph_node *node, | |
415 int edge_growth) | |
416 { | |
417 int max_callers; | |
418 struct cgraph_edge *e; | |
419 gcc_checking_assert (edge_growth > 0); | |
420 | |
421 /* First quickly check if NODE is removable at all. */ | |
422 if (DECL_EXTERNAL (node->decl)) | |
423 return true; | |
424 if (!node->can_remove_if_no_direct_calls_and_refs_p () | |
425 || node->address_taken) | |
426 return true; | |
427 | |
428 max_callers = ipa_fn_summaries->get (node)->size * 4 / edge_growth + 2; | |
429 | |
430 for (e = node->callers; e; e = e->next_caller) | |
431 { | |
432 max_callers--; | |
433 if (!max_callers | |
434 || cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR) | |
435 return true; | |
436 } | |
437 | |
438 ipa_ref *ref; | |
439 FOR_EACH_ALIAS (node, ref) | |
440 if (check_callers (dyn_cast <cgraph_node *> (ref->referring), &max_callers)) | |
441 return true; | |
442 | |
443 /* Unlike for functions called once, we play unsafe with | |
444 COMDATs. We can allow that since we know functions | |
445 in consideration are small (and thus risk is small) and | |
446 moreover grow estimates already accounts that COMDAT | |
447 functions may or may not disappear when eliminated from | |
448 current unit. With good probability making aggressive | |
449 choice in all units is going to make overall program | |
450 smaller. */ | |
451 if (DECL_COMDAT (node->decl)) | |
452 { | |
453 if (!node->can_remove_if_no_direct_calls_p ()) | |
454 return true; | |
455 } | |
456 else if (!node->will_be_removed_from_program_if_no_direct_calls_p ()) | |
457 return true; | |
458 | |
459 return estimate_growth (node) > 0; | |
460 } |