annotate gcc/ipa-profile.c @ 145:1830386684a0

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