]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ipa-profile.c
Fix ICE in speculative_call_info
[thirdparty/gcc.git] / gcc / ipa-profile.c
CommitLineData
08f835dc 1/* Basic IPA optimizations based on profile.
8d9254fc 2 Copyright (C) 2003-2020 Free Software Foundation, Inc.
08f835dc
JH
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
19
daf5c770
JH
20/* ipa-profile pass implements the following analysis propagating profille
21 inter-procedurally.
22
23 - Count histogram construction. This is a histogram analyzing how much
24 time is spent executing statements with a given execution count read
1c5fd343 25 from profile feedback. This histogram is complete only with LTO,
daf5c770
JH
26 otherwise it contains information only about the current unit.
27
daf5c770
JH
28 The information is used to set hot/cold thresholds.
29 - Next speculative indirect call resolution is performed: the local
30 profile pass assigns profile-id to each function and provide us with a
31 histogram specifying the most common target. We look up the callgraph
32 node corresponding to the target and produce a speculative call.
33
34 This call may or may not survive through IPA optimization based on decision
35 of inliner.
36 - Finally we propagate the following flags: unlikely executed, executed
37 once, executed at startup and executed at exit. These flags are used to
026c3cfd 38 control code size/performance threshold and code placement (by producing
daf5c770 39 .text.unlikely/.text.hot/.text.startup/.text.exit subsections). */
08f835dc
JH
40#include "config.h"
41#include "system.h"
42#include "coretypes.h"
c7131fb2 43#include "backend.h"
4d648807 44#include "tree.h"
c7131fb2 45#include "gimple.h"
957060b5
AM
46#include "predict.h"
47#include "alloc-pool.h"
48#include "tree-pass.h"
49#include "cgraph.h"
50#include "data-streamer.h"
5be5c238 51#include "gimple-iterator.h"
08f835dc 52#include "ipa-utils.h"
08f835dc 53#include "profile.h"
08f835dc 54#include "value-prof.h"
08f835dc 55#include "tree-inline.h"
dd912cb8 56#include "symbol-summary.h"
8bc5448f 57#include "tree-vrp.h"
c582198b 58#include "ipa-prop.h"
27d020cf 59#include "ipa-fnsummary.h"
08f835dc
JH
60
61/* Entry in the histogram. */
62
63struct histogram_entry
64{
65 gcov_type count;
66 int time;
67 int size;
68};
69
70/* Histogram of profile values.
71 The histogram is represented as an ordered vector of entries allocated via
72 histogram_pool. During construction a separate hashtable is kept to lookup
73 duplicate entries. */
74
75vec<histogram_entry *> histogram;
fcb87c50 76static object_allocator<histogram_entry> histogram_pool ("IPA histogram");
08f835dc
JH
77
78/* Hashtable support for storing SSA names hashed by their SSA_NAME_VAR. */
79
8d67ee55 80struct histogram_hash : nofree_ptr_hash <histogram_entry>
08f835dc 81{
67f58944
TS
82 static inline hashval_t hash (const histogram_entry *);
83 static inline int equal (const histogram_entry *, const histogram_entry *);
08f835dc
JH
84};
85
86inline hashval_t
87histogram_hash::hash (const histogram_entry *val)
88{
89 return val->count;
90}
91
92inline int
93histogram_hash::equal (const histogram_entry *val, const histogram_entry *val2)
94{
95 return val->count == val2->count;
96}
97
98/* Account TIME and SIZE executed COUNT times into HISTOGRAM.
99 HASHTABLE is the on-side hash kept to avoid duplicates. */
100
101static void
c203e8a7 102account_time_size (hash_table<histogram_hash> *hashtable,
08f835dc
JH
103 vec<histogram_entry *> &histogram,
104 gcov_type count, int time, int size)
105{
106 histogram_entry key = {count, 0, 0};
c203e8a7 107 histogram_entry **val = hashtable->find_slot (&key, INSERT);
08f835dc
JH
108
109 if (!*val)
110 {
d7809518 111 *val = histogram_pool.allocate ();
08f835dc
JH
112 **val = key;
113 histogram.safe_push (*val);
114 }
115 (*val)->time += time;
116 (*val)->size += size;
117}
118
119int
120cmp_counts (const void *v1, const void *v2)
121{
122 const histogram_entry *h1 = *(const histogram_entry * const *)v1;
123 const histogram_entry *h2 = *(const histogram_entry * const *)v2;
124 if (h1->count < h2->count)
125 return 1;
126 if (h1->count > h2->count)
127 return -1;
128 return 0;
129}
130
131/* Dump HISTOGRAM to FILE. */
132
133static void
134dump_histogram (FILE *file, vec<histogram_entry *> histogram)
135{
136 unsigned int i;
137 gcov_type overall_time = 0, cumulated_time = 0, cumulated_size = 0, overall_size = 0;
138
139 fprintf (dump_file, "Histogram:\n");
140 for (i = 0; i < histogram.length (); i++)
141 {
142 overall_time += histogram[i]->count * histogram[i]->time;
143 overall_size += histogram[i]->size;
144 }
145 if (!overall_time)
146 overall_time = 1;
147 if (!overall_size)
148 overall_size = 1;
149 for (i = 0; i < histogram.length (); i++)
150 {
151 cumulated_time += histogram[i]->count * histogram[i]->time;
152 cumulated_size += histogram[i]->size;
16998094 153 fprintf (file, " %" PRId64": time:%i (%2.2f) size:%i (%2.2f)\n",
a9243bfc 154 (int64_t) histogram[i]->count,
08f835dc
JH
155 histogram[i]->time,
156 cumulated_time * 100.0 / overall_time,
157 histogram[i]->size,
158 cumulated_size * 100.0 / overall_size);
159 }
160}
161
f1ba88b1
XHL
162/* Structure containing speculative target information from profile. */
163
164struct speculative_call_target
165{
166 speculative_call_target (unsigned int id = 0, int prob = 0)
167 : target_id (id), target_probability (prob)
168 {
169 }
170
171 /* Profile_id of target obtained from profile. */
172 unsigned int target_id;
173 /* Probability that call will land in function with target_id. */
174 unsigned int target_probability;
175};
176
177class speculative_call_summary
178{
179public:
180 speculative_call_summary () : speculative_call_targets ()
181 {}
182
183 auto_vec<speculative_call_target> speculative_call_targets;
184
185 void dump (FILE *f);
186
187};
188
189 /* Class to manage call summaries. */
190
191class ipa_profile_call_summaries
192 : public call_summary<speculative_call_summary *>
193{
194public:
195 ipa_profile_call_summaries (symbol_table *table)
196 : call_summary<speculative_call_summary *> (table)
197 {}
198
199 /* Duplicate info when an edge is cloned. */
200 virtual void duplicate (cgraph_edge *, cgraph_edge *,
201 speculative_call_summary *old_sum,
202 speculative_call_summary *new_sum);
203};
204
205static ipa_profile_call_summaries *call_sums = NULL;
206
207/* Dump all information in speculative call summary to F. */
208
209void
210speculative_call_summary::dump (FILE *f)
211{
212 cgraph_node *n2;
213
214 unsigned spec_count = speculative_call_targets.length ();
215 for (unsigned i = 0; i < spec_count; i++)
216 {
217 speculative_call_target item = speculative_call_targets[i];
218 n2 = find_func_by_profile_id (item.target_id);
219 if (n2)
220 fprintf (f, " The %i speculative target is %s with prob %3.2f\n", i,
221 n2->dump_name (),
222 item.target_probability / (float) REG_BR_PROB_BASE);
223 else
224 fprintf (f, " The %i speculative target is %u with prob %3.2f\n", i,
225 item.target_id,
226 item.target_probability / (float) REG_BR_PROB_BASE);
227 }
228}
229
230/* Duplicate info when an edge is cloned. */
231
232void
233ipa_profile_call_summaries::duplicate (cgraph_edge *, cgraph_edge *,
234 speculative_call_summary *old_sum,
235 speculative_call_summary *new_sum)
236{
237 if (!old_sum)
238 return;
239
240 unsigned old_count = old_sum->speculative_call_targets.length ();
241 if (!old_count)
242 return;
243
244 new_sum->speculative_call_targets.reserve_exact (old_count);
245 new_sum->speculative_call_targets.quick_grow_cleared (old_count);
246
247 for (unsigned i = 0; i < old_count; i++)
248 {
249 new_sum->speculative_call_targets[i]
250 = old_sum->speculative_call_targets[i];
251 }
252}
253
254/* Collect histogram and speculative target summaries from CFG profiles. */
08f835dc
JH
255
256static void
257ipa_profile_generate_summary (void)
258{
259 struct cgraph_node *node;
260 gimple_stmt_iterator gsi;
08f835dc
JH
261 basic_block bb;
262
c203e8a7 263 hash_table<histogram_hash> hashtable (10);
f1ba88b1
XHL
264
265 gcc_checking_assert (!call_sums);
266 call_sums = new ipa_profile_call_summaries (symtab);
267
08f835dc 268 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
e7a74006
JH
269 if (ENTRY_BLOCK_PTR_FOR_FN (DECL_STRUCT_FUNCTION (node->decl))->count.ipa_p ())
270 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
271 {
272 int time = 0;
273 int size = 0;
274 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
275 {
276 gimple *stmt = gsi_stmt (gsi);
277 if (gimple_code (stmt) == GIMPLE_CALL
278 && !gimple_call_fndecl (stmt))
279 {
280 histogram_value h;
281 h = gimple_histogram_value_of_type
282 (DECL_STRUCT_FUNCTION (node->decl),
283 stmt, HIST_TYPE_INDIR_CALL);
284 /* No need to do sanity check: gimple_ic_transform already
285 takes away bad histograms. */
286 if (h)
287 {
92d41717 288 gcov_type val, count, all;
f1ba88b1
XHL
289 struct cgraph_edge *e = node->get_edge (stmt);
290 if (e && !e->indirect_unknown_callee)
291 continue;
292
293 speculative_call_summary *csum
294 = call_sums->get_create (e);
295
296 for (unsigned j = 0; j < GCOV_TOPN_VALUES; j++)
e7a74006 297 {
f1ba88b1
XHL
298 if (!get_nth_most_common_value (NULL, "indirect call",
299 h, &val, &count, &all,
300 j))
e7a74006 301 continue;
92d41717 302
f1ba88b1
XHL
303 if (val == 0)
304 continue;
305
306 speculative_call_target item (
307 val, GCOV_COMPUTE_SCALE (count, all));
308 if (item.target_probability > REG_BR_PROB_BASE)
e7a74006
JH
309 {
310 if (dump_file)
f1ba88b1
XHL
311 fprintf (dump_file,
312 "Probability capped to 1\n");
313 item.target_probability = REG_BR_PROB_BASE;
e7a74006 314 }
f1ba88b1 315 csum->speculative_call_targets.safe_push (item);
e7a74006 316 }
f1ba88b1 317
e7a74006
JH
318 gimple_remove_histogram_value (DECL_STRUCT_FUNCTION (node->decl),
319 stmt, h);
320 }
321 }
322 time += estimate_num_insns (stmt, &eni_time_weights);
323 size += estimate_num_insns (stmt, &eni_size_weights);
324 }
325 if (bb->count.ipa_p () && bb->count.initialized_p ())
326 account_time_size (&hashtable, histogram, bb->count.ipa ().to_gcov_type (),
327 time, size);
328 }
08f835dc
JH
329 histogram.qsort (cmp_counts);
330}
331
f1ba88b1
XHL
332/* Serialize the speculative summary info for LTO. */
333
334static void
335ipa_profile_write_edge_summary (lto_simple_output_block *ob,
336 speculative_call_summary *csum)
337{
338 unsigned len = 0;
339
340 len = csum->speculative_call_targets.length ();
341
342 gcc_assert (len <= GCOV_TOPN_VALUES);
343
344 streamer_write_hwi_stream (ob->main_stream, len);
345
346 if (len)
347 {
348 unsigned spec_count = csum->speculative_call_targets.length ();
349 for (unsigned i = 0; i < spec_count; i++)
350 {
351 speculative_call_target item = csum->speculative_call_targets[i];
352 gcc_assert (item.target_id);
353 streamer_write_hwi_stream (ob->main_stream, item.target_id);
354 streamer_write_hwi_stream (ob->main_stream, item.target_probability);
355 }
356 }
357}
358
08f835dc
JH
359/* Serialize the ipa info for lto. */
360
361static void
362ipa_profile_write_summary (void)
363{
364 struct lto_simple_output_block *ob
365 = lto_create_simple_output_block (LTO_section_ipa_profile);
366 unsigned int i;
367
c3284718 368 streamer_write_uhwi_stream (ob->main_stream, histogram.length ());
08f835dc
JH
369 for (i = 0; i < histogram.length (); i++)
370 {
371 streamer_write_gcov_count_stream (ob->main_stream, histogram[i]->count);
372 streamer_write_uhwi_stream (ob->main_stream, histogram[i]->time);
373 streamer_write_uhwi_stream (ob->main_stream, histogram[i]->size);
374 }
f1ba88b1
XHL
375
376 if (!call_sums)
377 return;
378
379 /* Serialize speculative targets information. */
380 unsigned int count = 0;
381 lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
382 lto_symtab_encoder_iterator lsei;
383 cgraph_node *node;
384
385 for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
386 lsei_next_function_in_partition (&lsei))
387 {
388 node = lsei_cgraph_node (lsei);
389 if (node->definition && node->has_gimple_body_p ()
390 && node->indirect_calls)
391 count++;
392 }
393
394 streamer_write_uhwi_stream (ob->main_stream, count);
395
396 /* Process all of the functions. */
397 for (lsei = lsei_start_function_in_partition (encoder);
398 !lsei_end_p (lsei) && count; lsei_next_function_in_partition (&lsei))
399 {
400 cgraph_node *node = lsei_cgraph_node (lsei);
401 if (node->definition && node->has_gimple_body_p ()
402 && node->indirect_calls)
403 {
404 int node_ref = lto_symtab_encoder_encode (encoder, node);
405 streamer_write_uhwi_stream (ob->main_stream, node_ref);
406
407 for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
408 {
409 speculative_call_summary *csum = call_sums->get_create (e);
410 ipa_profile_write_edge_summary (ob, csum);
411 }
412 }
413 }
414
08f835dc
JH
415 lto_destroy_simple_output_block (ob);
416}
417
f1ba88b1
XHL
418/* Dump all profile summary data for all cgraph nodes and edges to file F. */
419
420static void
421ipa_profile_dump_all_summaries (FILE *f)
422{
423 fprintf (dump_file,
424 "\n========== IPA-profile speculative targets: ==========\n");
425 cgraph_node *node;
426 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
427 {
428 fprintf (f, "\nSummary for node %s:\n", node->dump_name ());
429 for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
430 {
431 fprintf (f, " Summary for %s of indirect edge %d:\n",
432 e->caller->dump_name (), e->lto_stmt_uid);
433 speculative_call_summary *csum = call_sums->get_create (e);
434 csum->dump (f);
435 }
436 }
437 fprintf (f, "\n\n");
438}
439
440/* Read speculative targets information about edge for LTO WPA. */
441
442static void
443ipa_profile_read_edge_summary (class lto_input_block *ib, cgraph_edge *edge)
444{
445 unsigned i, len;
446
447 len = streamer_read_hwi (ib);
448 gcc_assert (len <= GCOV_TOPN_VALUES);
449
450 speculative_call_summary *csum = call_sums->get_create (edge);
451
452 for (i = 0; i < len; i++)
453 {
84a3effa
ML
454 unsigned int target_id = streamer_read_hwi (ib);
455 int target_probability = streamer_read_hwi (ib);
456 speculative_call_target item (target_id, target_probability);
f1ba88b1
XHL
457 csum->speculative_call_targets.safe_push (item);
458 }
459}
460
461/* Read profile speculative targets section information for LTO WPA. */
462
463static void
464ipa_profile_read_summary_section (struct lto_file_decl_data *file_data,
465 class lto_input_block *ib)
466{
467 if (!ib)
468 return;
469
470 lto_symtab_encoder_t encoder = file_data->symtab_node_encoder;
471
472 unsigned int count = streamer_read_uhwi (ib);
473
474 unsigned int i;
475 unsigned int index;
476 cgraph_node * node;
477
478 for (i = 0; i < count; i++)
479 {
480 index = streamer_read_uhwi (ib);
481 encoder = file_data->symtab_node_encoder;
482 node
483 = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref (encoder, index));
484
485 for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
486 ipa_profile_read_edge_summary (ib, e);
487 }
488}
489
490/* Deserialize the IPA histogram and speculative targets summary info for LTO.
491 */
08f835dc
JH
492
493static void
494ipa_profile_read_summary (void)
495{
496 struct lto_file_decl_data ** file_data_vec
497 = lto_get_file_decl_data ();
498 struct lto_file_decl_data * file_data;
08f835dc
JH
499 int j = 0;
500
c203e8a7 501 hash_table<histogram_hash> hashtable (10);
08f835dc 502
f1ba88b1
XHL
503 gcc_checking_assert (!call_sums);
504 call_sums = new ipa_profile_call_summaries (symtab);
505
08f835dc
JH
506 while ((file_data = file_data_vec[j++]))
507 {
508 const char *data;
509 size_t len;
99b1c316 510 class lto_input_block *ib
08f835dc
JH
511 = lto_create_simple_input_block (file_data,
512 LTO_section_ipa_profile,
513 &data, &len);
514 if (ib)
515 {
516 unsigned int num = streamer_read_uhwi (ib);
517 unsigned int n;
518 for (n = 0; n < num; n++)
519 {
520 gcov_type count = streamer_read_gcov_count (ib);
521 int time = streamer_read_uhwi (ib);
522 int size = streamer_read_uhwi (ib);
c203e8a7 523 account_time_size (&hashtable, histogram,
08f835dc
JH
524 count, time, size);
525 }
f1ba88b1
XHL
526
527 ipa_profile_read_summary_section (file_data, ib);
528
08f835dc
JH
529 lto_destroy_simple_input_block (file_data,
530 LTO_section_ipa_profile,
531 ib, data, len);
532 }
533 }
08f835dc
JH
534 histogram.qsort (cmp_counts);
535}
536
537/* Data used by ipa_propagate_frequency. */
538
539struct ipa_propagate_frequency_data
540{
1ede94c5 541 cgraph_node *function_symbol;
08f835dc
JH
542 bool maybe_unlikely_executed;
543 bool maybe_executed_once;
544 bool only_called_at_startup;
545 bool only_called_at_exit;
546};
547
548/* Worker for ipa_propagate_frequency_1. */
549
550static bool
551ipa_propagate_frequency_1 (struct cgraph_node *node, void *data)
552{
553 struct ipa_propagate_frequency_data *d;
554 struct cgraph_edge *edge;
555
556 d = (struct ipa_propagate_frequency_data *)data;
557 for (edge = node->callers;
558 edge && (d->maybe_unlikely_executed || d->maybe_executed_once
559 || d->only_called_at_startup || d->only_called_at_exit);
560 edge = edge->next_caller)
561 {
1ede94c5 562 if (edge->caller != d->function_symbol)
08f835dc
JH
563 {
564 d->only_called_at_startup &= edge->caller->only_called_at_startup;
565 /* It makes sense to put main() together with the static constructors.
566 It will be executed for sure, but rest of functions called from
567 main are definitely not at startup only. */
67348ccc 568 if (MAIN_NAME_P (DECL_NAME (edge->caller->decl)))
08f835dc
JH
569 d->only_called_at_startup = 0;
570 d->only_called_at_exit &= edge->caller->only_called_at_exit;
571 }
daf5c770
JH
572
573 /* When profile feedback is available, do not try to propagate too hard;
574 counts are already good guide on function frequencies and roundoff
575 errors can make us to push function into unlikely section even when
576 it is executed by the train run. Transfer the function only if all
577 callers are unlikely executed. */
1ede94c5 578 if (profile_info
35d93d1d 579 && !(edge->callee->count.ipa () == profile_count::zero ())
daf5c770 580 && (edge->caller->frequency != NODE_FREQUENCY_UNLIKELY_EXECUTED
a62bfab5
ML
581 || (edge->caller->inlined_to
582 && edge->caller->inlined_to->frequency
daf5c770
JH
583 != NODE_FREQUENCY_UNLIKELY_EXECUTED)))
584 d->maybe_unlikely_executed = false;
35d93d1d
JH
585 if (edge->count.ipa ().initialized_p ()
586 && !edge->count.ipa ().nonzero_p ())
08f835dc
JH
587 continue;
588 switch (edge->caller->frequency)
589 {
590 case NODE_FREQUENCY_UNLIKELY_EXECUTED:
591 break;
592 case NODE_FREQUENCY_EXECUTED_ONCE:
56f62793
ML
593 {
594 if (dump_file && (dump_flags & TDF_DETAILS))
595 fprintf (dump_file, " Called by %s that is executed once\n",
3629ff8a 596 edge->caller->dump_name ());
56f62793
ML
597 d->maybe_unlikely_executed = false;
598 ipa_call_summary *s = ipa_call_summaries->get (edge);
599 if (s != NULL && s->loop_depth)
600 {
601 d->maybe_executed_once = false;
602 if (dump_file && (dump_flags & TDF_DETAILS))
603 fprintf (dump_file, " Called in loop\n");
604 }
605 break;
606 }
08f835dc
JH
607 case NODE_FREQUENCY_HOT:
608 case NODE_FREQUENCY_NORMAL:
609 if (dump_file && (dump_flags & TDF_DETAILS))
610 fprintf (dump_file, " Called by %s that is normal or hot\n",
3629ff8a 611 edge->caller->dump_name ());
08f835dc
JH
612 d->maybe_unlikely_executed = false;
613 d->maybe_executed_once = false;
614 break;
615 }
616 }
617 return edge != NULL;
618}
619
daf5c770
JH
620/* Return ture if NODE contains hot calls. */
621
622bool
623contains_hot_call_p (struct cgraph_node *node)
624{
625 struct cgraph_edge *e;
626 for (e = node->callees; e; e = e->next_callee)
3dafb85c 627 if (e->maybe_hot_p ())
daf5c770
JH
628 return true;
629 else if (!e->inline_failed
630 && contains_hot_call_p (e->callee))
631 return true;
632 for (e = node->indirect_calls; e; e = e->next_callee)
3dafb85c 633 if (e->maybe_hot_p ())
daf5c770
JH
634 return true;
635 return false;
636}
637
08f835dc
JH
638/* See if the frequency of NODE can be updated based on frequencies of its
639 callers. */
640bool
641ipa_propagate_frequency (struct cgraph_node *node)
642{
1ede94c5 643 struct ipa_propagate_frequency_data d = {node, true, true, true, true};
08f835dc
JH
644 bool changed = false;
645
67914693 646 /* We cannot propagate anything useful about externally visible functions
08f835dc 647 nor about virtuals. */
87f94429 648 if (!node->local
67348ccc 649 || node->alias
2bf86c84
JH
650 || (opt_for_fn (node->decl, flag_devirtualize)
651 && DECL_VIRTUAL_P (node->decl)))
08f835dc 652 return false;
67348ccc 653 gcc_assert (node->analyzed);
08f835dc 654 if (dump_file && (dump_flags & TDF_DETAILS))
3629ff8a 655 fprintf (dump_file, "Processing frequency %s\n", node->dump_name ());
08f835dc 656
1ede94c5
JH
657 node->call_for_symbol_and_aliases (ipa_propagate_frequency_1, &d,
658 true);
08f835dc
JH
659
660 if ((d.only_called_at_startup && !d.only_called_at_exit)
661 && !node->only_called_at_startup)
662 {
663 node->only_called_at_startup = true;
664 if (dump_file)
665 fprintf (dump_file, "Node %s promoted to only called at startup.\n",
3629ff8a 666 node->dump_name ());
08f835dc
JH
667 changed = true;
668 }
669 if ((d.only_called_at_exit && !d.only_called_at_startup)
670 && !node->only_called_at_exit)
671 {
672 node->only_called_at_exit = true;
673 if (dump_file)
674 fprintf (dump_file, "Node %s promoted to only called at exit.\n",
3629ff8a 675 node->dump_name ());
08f835dc
JH
676 changed = true;
677 }
daf5c770
JH
678
679 /* With profile we can decide on hot/normal based on count. */
1bad9c18 680 if (node->count. ipa().initialized_p ())
daf5c770
JH
681 {
682 bool hot = false;
1bad9c18
JH
683 if (!(node->count. ipa() == profile_count::zero ())
684 && node->count. ipa() >= get_hot_bb_threshold ())
daf5c770
JH
685 hot = true;
686 if (!hot)
687 hot |= contains_hot_call_p (node);
688 if (hot)
689 {
690 if (node->frequency != NODE_FREQUENCY_HOT)
691 {
692 if (dump_file)
693 fprintf (dump_file, "Node %s promoted to hot.\n",
3629ff8a 694 node->dump_name ());
daf5c770
JH
695 node->frequency = NODE_FREQUENCY_HOT;
696 return true;
697 }
698 return false;
699 }
700 else if (node->frequency == NODE_FREQUENCY_HOT)
701 {
702 if (dump_file)
703 fprintf (dump_file, "Node %s reduced to normal.\n",
3629ff8a 704 node->dump_name ());
daf5c770
JH
705 node->frequency = NODE_FREQUENCY_NORMAL;
706 changed = true;
707 }
708 }
08f835dc
JH
709 /* These come either from profile or user hints; never update them. */
710 if (node->frequency == NODE_FREQUENCY_HOT
711 || node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
712 return changed;
713 if (d.maybe_unlikely_executed)
714 {
715 node->frequency = NODE_FREQUENCY_UNLIKELY_EXECUTED;
716 if (dump_file)
717 fprintf (dump_file, "Node %s promoted to unlikely executed.\n",
3629ff8a 718 node->dump_name ());
08f835dc
JH
719 changed = true;
720 }
721 else if (d.maybe_executed_once && node->frequency != NODE_FREQUENCY_EXECUTED_ONCE)
722 {
723 node->frequency = NODE_FREQUENCY_EXECUTED_ONCE;
724 if (dump_file)
725 fprintf (dump_file, "Node %s promoted to executed once.\n",
3629ff8a 726 node->dump_name ());
08f835dc
JH
727 changed = true;
728 }
729 return changed;
730}
731
d200a49f
JH
732/* Check that number of arguments of N agrees with E.
733 Be conservative when summaries are not present. */
734
735static bool
736check_argument_count (struct cgraph_node *n, struct cgraph_edge *e)
737{
738 if (!ipa_node_params_sum || !ipa_edge_args_sum)
739 return true;
740 class ipa_node_params *info = IPA_NODE_REF (n->function_symbol ());
741 if (!info)
742 return true;
743 ipa_edge_args *e_info = IPA_EDGE_REF (e);
d772e360 744 if (!e_info)
d200a49f
JH
745 return true;
746 if (ipa_get_param_count (info) != ipa_get_cs_argument_count (e_info)
747 && (ipa_get_param_count (info) >= ipa_get_cs_argument_count (e_info)
748 || !stdarg_p (TREE_TYPE (n->decl))))
749 return false;
750 return true;
751}
752
08f835dc
JH
753/* Simple ipa profile pass propagating frequencies across the callgraph. */
754
755static unsigned int
756ipa_profile (void)
757{
758 struct cgraph_node **order;
759 struct cgraph_edge *e;
760 int order_pos;
761 bool something_changed = false;
762 int i;
763 gcov_type overall_time = 0, cutoff = 0, cumulated = 0, overall_size = 0;
764 struct cgraph_node *n,*n2;
765 int nindirect = 0, ncommon = 0, nunknown = 0, nuseless = 0, nconverted = 0;
95d81ba5 766 int nmismatch = 0, nimpossible = 0;
08f835dc 767 bool node_map_initialized = false;
f1ba88b1 768 gcov_type threshold;
08f835dc
JH
769
770 if (dump_file)
771 dump_histogram (dump_file, histogram);
772 for (i = 0; i < (int)histogram.length (); i++)
773 {
774 overall_time += histogram[i]->count * histogram[i]->time;
775 overall_size += histogram[i]->size;
776 }
f1ba88b1 777 threshold = 0;
08f835dc
JH
778 if (overall_time)
779 {
08f835dc 780 gcc_assert (overall_size);
08f835dc 781
028d4092 782 cutoff = (overall_time * param_hot_bb_count_ws_permille + 500) / 1000;
08f835dc
JH
783 for (i = 0; cumulated < cutoff; i++)
784 {
785 cumulated += histogram[i]->count * histogram[i]->time;
786 threshold = histogram[i]->count;
787 }
788 if (!threshold)
789 threshold = 1;
790 if (dump_file)
791 {
792 gcov_type cumulated_time = 0, cumulated_size = 0;
793
794 for (i = 0;
795 i < (int)histogram.length () && histogram[i]->count >= threshold;
796 i++)
797 {
798 cumulated_time += histogram[i]->count * histogram[i]->time;
799 cumulated_size += histogram[i]->size;
800 }
16998094 801 fprintf (dump_file, "Determined min count: %" PRId64
08f835dc 802 " Time:%3.2f%% Size:%3.2f%%\n",
a9243bfc 803 (int64_t)threshold,
08f835dc
JH
804 cumulated_time * 100.0 / overall_time,
805 cumulated_size * 100.0 / overall_size);
806 }
512cc015 807
e53f77c6 808 if (in_lto_p)
08f835dc
JH
809 {
810 if (dump_file)
e53f77c6 811 fprintf (dump_file, "Setting hotness threshold in LTO mode.\n");
08f835dc
JH
812 set_hot_bb_threshold (threshold);
813 }
814 }
c3284718 815 histogram.release ();
d7809518 816 histogram_pool.release ();
08f835dc 817
f1ba88b1
XHL
818 /* Produce speculative calls: we saved common target from profiling into
819 e->target_id. Now, at link time, we can look up corresponding
08f835dc
JH
820 function node and produce speculative call. */
821
f1ba88b1
XHL
822 gcc_checking_assert (call_sums);
823
824 if (dump_file)
825 {
826 if (!node_map_initialized)
827 init_node_map (false);
828 node_map_initialized = true;
829
830 ipa_profile_dump_all_summaries (dump_file);
831 }
832
08f835dc
JH
833 FOR_EACH_DEFINED_FUNCTION (n)
834 {
835 bool update = false;
836
1ede94c5
JH
837 if (!opt_for_fn (n->decl, flag_ipa_profile))
838 continue;
839
08f835dc
JH
840 for (e = n->indirect_calls; e; e = e->next_callee)
841 {
3995f3a2 842 if (n->count.initialized_p ())
08f835dc 843 nindirect++;
f1ba88b1
XHL
844
845 speculative_call_summary *csum = call_sums->get_create (e);
846 unsigned spec_count = csum->speculative_call_targets.length ();
847 if (spec_count)
08f835dc
JH
848 {
849 if (!node_map_initialized)
f1ba88b1 850 init_node_map (false);
08f835dc
JH
851 node_map_initialized = true;
852 ncommon++;
f1ba88b1
XHL
853
854 if (in_lto_p)
855 {
856 if (dump_file)
857 {
858 fprintf (dump_file,
859 "Updating hotness threshold in LTO mode.\n");
860 fprintf (dump_file, "Updated min count: %" PRId64 "\n",
861 (int64_t) threshold / spec_count);
862 }
863 set_hot_bb_threshold (threshold / spec_count);
864 }
865
866 unsigned speculative_id = 0;
867 bool speculative_found = false;
868 for (unsigned i = 0; i < spec_count; i++)
869 {
870 speculative_call_target item
871 = csum->speculative_call_targets[i];
872 n2 = find_func_by_profile_id (item.target_id);
08f835dc
JH
873 if (n2)
874 {
875 if (dump_file)
876 {
877 fprintf (dump_file, "Indirect call -> direct call from"
464d0118
ML
878 " other module %s => %s, prob %3.2f\n",
879 n->dump_name (),
880 n2->dump_name (),
f1ba88b1
XHL
881 item.target_probability
882 / (float) REG_BR_PROB_BASE);
08f835dc 883 }
f1ba88b1 884 if (item.target_probability < REG_BR_PROB_BASE / 2)
08f835dc
JH
885 {
886 nuseless++;
887 if (dump_file)
888 fprintf (dump_file,
889 "Not speculating: probability is too low.\n");
890 }
3dafb85c 891 else if (!e->maybe_hot_p ())
08f835dc
JH
892 {
893 nuseless++;
894 if (dump_file)
895 fprintf (dump_file,
896 "Not speculating: call is cold.\n");
897 }
d52f5295
ML
898 else if (n2->get_availability () <= AVAIL_INTERPOSABLE
899 && n2->can_be_discarded_p ())
08f835dc
JH
900 {
901 nuseless++;
902 if (dump_file)
903 fprintf (dump_file,
904 "Not speculating: target is overwritable "
905 "and can be discarded.\n");
906 }
7b34a284 907 else if (!check_argument_count (n2, e))
95d81ba5
JH
908 {
909 nmismatch++;
910 if (dump_file)
911 fprintf (dump_file,
912 "Not speculating: "
4e8e460b 913 "parameter count mismatch\n");
95d81ba5
JH
914 }
915 else if (e->indirect_info->polymorphic
916 && !opt_for_fn (n->decl, flag_devirtualize)
917 && !possible_polymorphic_call_target_p (e, n2))
918 {
919 nimpossible++;
920 if (dump_file)
921 fprintf (dump_file,
922 "Not speculating: "
923 "function is not in the polymorphic "
924 "call target list\n");
925 }
08f835dc
JH
926 else
927 {
928 /* Target may be overwritable, but profile says that
929 control flow goes to this particular implementation
930 of N2. Speculate on the local alias to allow inlining.
931 */
d52f5295 932 if (!n2->can_be_discarded_p ())
5b79657a
JH
933 {
934 cgraph_node *alias;
d52f5295 935 alias = dyn_cast<cgraph_node *> (n2->noninterposable_alias ());
5b79657a
JH
936 if (alias)
937 n2 = alias;
938 }
08f835dc 939 nconverted++;
f1ba88b1
XHL
940 e->make_speculative (n2,
941 e->count.apply_probability (
942 item.target_probability),
943 speculative_id,
944 item.target_probability);
08f835dc 945 update = true;
f1ba88b1
XHL
946 speculative_id++;
947 speculative_found = true;
08f835dc
JH
948 }
949 }
950 else
951 {
952 if (dump_file)
953 fprintf (dump_file, "Function with profile-id %i not found.\n",
f1ba88b1 954 item.target_id);
08f835dc
JH
955 nunknown++;
956 }
f1ba88b1
XHL
957 }
958 if (speculative_found)
959 e->indirect_info->num_speculative_call_targets = speculative_id;
08f835dc
JH
960 }
961 }
962 if (update)
0bceb671 963 ipa_update_overall_fn_summary (n);
08f835dc
JH
964 }
965 if (node_map_initialized)
966 del_node_map ();
967 if (dump_file && nindirect)
968 fprintf (dump_file,
969 "%i indirect calls trained.\n"
970 "%i (%3.2f%%) have common target.\n"
971 "%i (%3.2f%%) targets was not found.\n"
95d81ba5
JH
972 "%i (%3.2f%%) targets had parameter count mismatch.\n"
973 "%i (%3.2f%%) targets was not in polymorphic call target list.\n"
08f835dc
JH
974 "%i (%3.2f%%) speculations seems useless.\n"
975 "%i (%3.2f%%) speculations produced.\n",
976 nindirect,
977 ncommon, ncommon * 100.0 / nindirect,
978 nunknown, nunknown * 100.0 / nindirect,
95d81ba5
JH
979 nmismatch, nmismatch * 100.0 / nindirect,
980 nimpossible, nimpossible * 100.0 / nindirect,
08f835dc
JH
981 nuseless, nuseless * 100.0 / nindirect,
982 nconverted, nconverted * 100.0 / nindirect);
983
3dafb85c 984 order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
08f835dc
JH
985 order_pos = ipa_reverse_postorder (order);
986 for (i = order_pos - 1; i >= 0; i--)
987 {
87f94429 988 if (order[i]->local
1ede94c5
JH
989 && opt_for_fn (order[i]->decl, flag_ipa_profile)
990 && ipa_propagate_frequency (order[i]))
08f835dc
JH
991 {
992 for (e = order[i]->callees; e; e = e->next_callee)
87f94429 993 if (e->callee->local && !e->callee->aux)
08f835dc
JH
994 {
995 something_changed = true;
67348ccc 996 e->callee->aux = (void *)1;
08f835dc
JH
997 }
998 }
67348ccc 999 order[i]->aux = NULL;
08f835dc
JH
1000 }
1001
1002 while (something_changed)
1003 {
1004 something_changed = false;
1005 for (i = order_pos - 1; i >= 0; i--)
1006 {
1ede94c5
JH
1007 if (order[i]->aux
1008 && opt_for_fn (order[i]->decl, flag_ipa_profile)
1009 && ipa_propagate_frequency (order[i]))
08f835dc
JH
1010 {
1011 for (e = order[i]->callees; e; e = e->next_callee)
87f94429 1012 if (e->callee->local && !e->callee->aux)
08f835dc
JH
1013 {
1014 something_changed = true;
67348ccc 1015 e->callee->aux = (void *)1;
08f835dc
JH
1016 }
1017 }
67348ccc 1018 order[i]->aux = NULL;
08f835dc
JH
1019 }
1020 }
1021 free (order);
f1ba88b1
XHL
1022
1023 if (dump_file && (dump_flags & TDF_DETAILS))
1024 symtab->dump (dump_file);
1025
08f835dc
JH
1026 return 0;
1027}
1028
08f835dc
JH
1029namespace {
1030
1031const pass_data pass_data_ipa_profile =
1032{
1033 IPA_PASS, /* type */
1034 "profile_estimate", /* name */
1035 OPTGROUP_NONE, /* optinfo_flags */
08f835dc
JH
1036 TV_IPA_PROFILE, /* tv_id */
1037 0, /* properties_required */
1038 0, /* properties_provided */
1039 0, /* properties_destroyed */
1040 0, /* todo_flags_start */
1041 0, /* todo_flags_finish */
1042};
1043
1044class pass_ipa_profile : public ipa_opt_pass_d
1045{
1046public:
c3284718
RS
1047 pass_ipa_profile (gcc::context *ctxt)
1048 : ipa_opt_pass_d (pass_data_ipa_profile, ctxt,
1049 ipa_profile_generate_summary, /* generate_summary */
1050 ipa_profile_write_summary, /* write_summary */
1051 ipa_profile_read_summary, /* read_summary */
1052 NULL, /* write_optimization_summary */
1053 NULL, /* read_optimization_summary */
1054 NULL, /* stmt_fixup */
1055 0, /* function_transform_todo_flags_start */
1056 NULL, /* function_transform */
1057 NULL) /* variable_transform */
08f835dc
JH
1058 {}
1059
1060 /* opt_pass methods: */
2bf86c84 1061 virtual bool gate (function *) { return flag_ipa_profile || in_lto_p; }
be55bfe6 1062 virtual unsigned int execute (function *) { return ipa_profile (); }
08f835dc
JH
1063
1064}; // class pass_ipa_profile
1065
1066} // anon namespace
1067
1068ipa_opt_pass_d *
1069make_pass_ipa_profile (gcc::context *ctxt)
1070{
1071 return new pass_ipa_profile (ctxt);
1072}