annotate gcc/ipa-profile.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
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.
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2 Copyright (C) 2003-2018 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 "params.h"
kono
parents:
diff changeset
55 #include "value-prof.h"
kono
parents:
diff changeset
56 #include "tree-inline.h"
kono
parents:
diff changeset
57 #include "symbol-summary.h"
kono
parents:
diff changeset
58 #include "tree-vrp.h"
kono
parents:
diff changeset
59 #include "ipa-prop.h"
kono
parents:
diff changeset
60 #include "ipa-fnsummary.h"
kono
parents:
diff changeset
61
kono
parents:
diff changeset
62 /* Entry in the histogram. */
kono
parents:
diff changeset
63
kono
parents:
diff changeset
64 struct histogram_entry
kono
parents:
diff changeset
65 {
kono
parents:
diff changeset
66 gcov_type count;
kono
parents:
diff changeset
67 int time;
kono
parents:
diff changeset
68 int size;
kono
parents:
diff changeset
69 };
kono
parents:
diff changeset
70
kono
parents:
diff changeset
71 /* Histogram of profile values.
kono
parents:
diff changeset
72 The histogram is represented as an ordered vector of entries allocated via
kono
parents:
diff changeset
73 histogram_pool. During construction a separate hashtable is kept to lookup
kono
parents:
diff changeset
74 duplicate entries. */
kono
parents:
diff changeset
75
kono
parents:
diff changeset
76 vec<histogram_entry *> histogram;
kono
parents:
diff changeset
77 static object_allocator<histogram_entry> histogram_pool ("IPA histogram");
kono
parents:
diff changeset
78
kono
parents:
diff changeset
79 /* Hashtable support for storing SSA names hashed by their SSA_NAME_VAR. */
kono
parents:
diff changeset
80
kono
parents:
diff changeset
81 struct histogram_hash : nofree_ptr_hash <histogram_entry>
kono
parents:
diff changeset
82 {
kono
parents:
diff changeset
83 static inline hashval_t hash (const histogram_entry *);
kono
parents:
diff changeset
84 static inline int equal (const histogram_entry *, const histogram_entry *);
kono
parents:
diff changeset
85 };
kono
parents:
diff changeset
86
kono
parents:
diff changeset
87 inline hashval_t
kono
parents:
diff changeset
88 histogram_hash::hash (const histogram_entry *val)
kono
parents:
diff changeset
89 {
kono
parents:
diff changeset
90 return val->count;
kono
parents:
diff changeset
91 }
kono
parents:
diff changeset
92
kono
parents:
diff changeset
93 inline int
kono
parents:
diff changeset
94 histogram_hash::equal (const histogram_entry *val, const histogram_entry *val2)
kono
parents:
diff changeset
95 {
kono
parents:
diff changeset
96 return val->count == val2->count;
kono
parents:
diff changeset
97 }
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99 /* Account TIME and SIZE executed COUNT times into HISTOGRAM.
kono
parents:
diff changeset
100 HASHTABLE is the on-side hash kept to avoid duplicates. */
kono
parents:
diff changeset
101
kono
parents:
diff changeset
102 static void
kono
parents:
diff changeset
103 account_time_size (hash_table<histogram_hash> *hashtable,
kono
parents:
diff changeset
104 vec<histogram_entry *> &histogram,
kono
parents:
diff changeset
105 gcov_type count, int time, int size)
kono
parents:
diff changeset
106 {
kono
parents:
diff changeset
107 histogram_entry key = {count, 0, 0};
kono
parents:
diff changeset
108 histogram_entry **val = hashtable->find_slot (&key, INSERT);
kono
parents:
diff changeset
109
kono
parents:
diff changeset
110 if (!*val)
kono
parents:
diff changeset
111 {
kono
parents:
diff changeset
112 *val = histogram_pool.allocate ();
kono
parents:
diff changeset
113 **val = key;
kono
parents:
diff changeset
114 histogram.safe_push (*val);
kono
parents:
diff changeset
115 }
kono
parents:
diff changeset
116 (*val)->time += time;
kono
parents:
diff changeset
117 (*val)->size += size;
kono
parents:
diff changeset
118 }
kono
parents:
diff changeset
119
kono
parents:
diff changeset
120 int
kono
parents:
diff changeset
121 cmp_counts (const void *v1, const void *v2)
kono
parents:
diff changeset
122 {
kono
parents:
diff changeset
123 const histogram_entry *h1 = *(const histogram_entry * const *)v1;
kono
parents:
diff changeset
124 const histogram_entry *h2 = *(const histogram_entry * const *)v2;
kono
parents:
diff changeset
125 if (h1->count < h2->count)
kono
parents:
diff changeset
126 return 1;
kono
parents:
diff changeset
127 if (h1->count > h2->count)
kono
parents:
diff changeset
128 return -1;
kono
parents:
diff changeset
129 return 0;
kono
parents:
diff changeset
130 }
kono
parents:
diff changeset
131
kono
parents:
diff changeset
132 /* Dump HISTOGRAM to FILE. */
kono
parents:
diff changeset
133
kono
parents:
diff changeset
134 static void
kono
parents:
diff changeset
135 dump_histogram (FILE *file, vec<histogram_entry *> histogram)
kono
parents:
diff changeset
136 {
kono
parents:
diff changeset
137 unsigned int i;
kono
parents:
diff changeset
138 gcov_type overall_time = 0, cumulated_time = 0, cumulated_size = 0, overall_size = 0;
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
kono
parents:
diff changeset
163 /* Collect histogram from CFG profiles. */
kono
parents:
diff changeset
164
kono
parents:
diff changeset
165 static void
kono
parents:
diff changeset
166 ipa_profile_generate_summary (void)
kono
parents:
diff changeset
167 {
kono
parents:
diff changeset
168 struct cgraph_node *node;
kono
parents:
diff changeset
169 gimple_stmt_iterator gsi;
kono
parents:
diff changeset
170 basic_block bb;
kono
parents:
diff changeset
171
kono
parents:
diff changeset
172 hash_table<histogram_hash> hashtable (10);
kono
parents:
diff changeset
173
kono
parents:
diff changeset
174 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
175 if (ENTRY_BLOCK_PTR_FOR_FN (DECL_STRUCT_FUNCTION (node->decl))->count.ipa_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
176 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
177 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
178 int time = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
179 int size = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
180 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
181 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
182 gimple *stmt = gsi_stmt (gsi);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
183 if (gimple_code (stmt) == GIMPLE_CALL
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
184 && !gimple_call_fndecl (stmt))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
185 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
186 histogram_value h;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
187 h = gimple_histogram_value_of_type
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
188 (DECL_STRUCT_FUNCTION (node->decl),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
189 stmt, HIST_TYPE_INDIR_CALL);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
190 /* No need to do sanity check: gimple_ic_transform already
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
191 takes away bad histograms. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
192 if (h)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
193 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
194 /* counter 0 is target, counter 1 is number of execution we called target,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
195 counter 2 is total number of executions. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
196 if (h->hvalue.counters[2])
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
197 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
198 struct cgraph_edge * e = node->get_edge (stmt);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
199 if (e && !e->indirect_unknown_callee)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
200 continue;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
201 e->indirect_info->common_target_id
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
202 = h->hvalue.counters [0];
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
203 e->indirect_info->common_target_probability
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
204 = GCOV_COMPUTE_SCALE (h->hvalue.counters [1], h->hvalue.counters [2]);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
205 if (e->indirect_info->common_target_probability > REG_BR_PROB_BASE)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
206 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
207 if (dump_file)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
208 fprintf (dump_file, "Probability capped to 1\n");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
209 e->indirect_info->common_target_probability = REG_BR_PROB_BASE;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
210 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
211 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
212 gimple_remove_histogram_value (DECL_STRUCT_FUNCTION (node->decl),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
213 stmt, h);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
214 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
215 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
216 time += estimate_num_insns (stmt, &eni_time_weights);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
217 size += estimate_num_insns (stmt, &eni_size_weights);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
218 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
219 if (bb->count.ipa_p () && bb->count.initialized_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
220 account_time_size (&hashtable, histogram, bb->count.ipa ().to_gcov_type (),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
221 time, size);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
222 }
111
kono
parents:
diff changeset
223 histogram.qsort (cmp_counts);
kono
parents:
diff changeset
224 }
kono
parents:
diff changeset
225
kono
parents:
diff changeset
226 /* Serialize the ipa info for lto. */
kono
parents:
diff changeset
227
kono
parents:
diff changeset
228 static void
kono
parents:
diff changeset
229 ipa_profile_write_summary (void)
kono
parents:
diff changeset
230 {
kono
parents:
diff changeset
231 struct lto_simple_output_block *ob
kono
parents:
diff changeset
232 = lto_create_simple_output_block (LTO_section_ipa_profile);
kono
parents:
diff changeset
233 unsigned int i;
kono
parents:
diff changeset
234
kono
parents:
diff changeset
235 streamer_write_uhwi_stream (ob->main_stream, histogram.length ());
kono
parents:
diff changeset
236 for (i = 0; i < histogram.length (); i++)
kono
parents:
diff changeset
237 {
kono
parents:
diff changeset
238 streamer_write_gcov_count_stream (ob->main_stream, histogram[i]->count);
kono
parents:
diff changeset
239 streamer_write_uhwi_stream (ob->main_stream, histogram[i]->time);
kono
parents:
diff changeset
240 streamer_write_uhwi_stream (ob->main_stream, histogram[i]->size);
kono
parents:
diff changeset
241 }
kono
parents:
diff changeset
242 lto_destroy_simple_output_block (ob);
kono
parents:
diff changeset
243 }
kono
parents:
diff changeset
244
kono
parents:
diff changeset
245 /* Deserialize the ipa info for lto. */
kono
parents:
diff changeset
246
kono
parents:
diff changeset
247 static void
kono
parents:
diff changeset
248 ipa_profile_read_summary (void)
kono
parents:
diff changeset
249 {
kono
parents:
diff changeset
250 struct lto_file_decl_data ** file_data_vec
kono
parents:
diff changeset
251 = lto_get_file_decl_data ();
kono
parents:
diff changeset
252 struct lto_file_decl_data * file_data;
kono
parents:
diff changeset
253 int j = 0;
kono
parents:
diff changeset
254
kono
parents:
diff changeset
255 hash_table<histogram_hash> hashtable (10);
kono
parents:
diff changeset
256
kono
parents:
diff changeset
257 while ((file_data = file_data_vec[j++]))
kono
parents:
diff changeset
258 {
kono
parents:
diff changeset
259 const char *data;
kono
parents:
diff changeset
260 size_t len;
kono
parents:
diff changeset
261 struct lto_input_block *ib
kono
parents:
diff changeset
262 = lto_create_simple_input_block (file_data,
kono
parents:
diff changeset
263 LTO_section_ipa_profile,
kono
parents:
diff changeset
264 &data, &len);
kono
parents:
diff changeset
265 if (ib)
kono
parents:
diff changeset
266 {
kono
parents:
diff changeset
267 unsigned int num = streamer_read_uhwi (ib);
kono
parents:
diff changeset
268 unsigned int n;
kono
parents:
diff changeset
269 for (n = 0; n < num; n++)
kono
parents:
diff changeset
270 {
kono
parents:
diff changeset
271 gcov_type count = streamer_read_gcov_count (ib);
kono
parents:
diff changeset
272 int time = streamer_read_uhwi (ib);
kono
parents:
diff changeset
273 int size = streamer_read_uhwi (ib);
kono
parents:
diff changeset
274 account_time_size (&hashtable, histogram,
kono
parents:
diff changeset
275 count, time, size);
kono
parents:
diff changeset
276 }
kono
parents:
diff changeset
277 lto_destroy_simple_input_block (file_data,
kono
parents:
diff changeset
278 LTO_section_ipa_profile,
kono
parents:
diff changeset
279 ib, data, len);
kono
parents:
diff changeset
280 }
kono
parents:
diff changeset
281 }
kono
parents:
diff changeset
282 histogram.qsort (cmp_counts);
kono
parents:
diff changeset
283 }
kono
parents:
diff changeset
284
kono
parents:
diff changeset
285 /* Data used by ipa_propagate_frequency. */
kono
parents:
diff changeset
286
kono
parents:
diff changeset
287 struct ipa_propagate_frequency_data
kono
parents:
diff changeset
288 {
kono
parents:
diff changeset
289 cgraph_node *function_symbol;
kono
parents:
diff changeset
290 bool maybe_unlikely_executed;
kono
parents:
diff changeset
291 bool maybe_executed_once;
kono
parents:
diff changeset
292 bool only_called_at_startup;
kono
parents:
diff changeset
293 bool only_called_at_exit;
kono
parents:
diff changeset
294 };
kono
parents:
diff changeset
295
kono
parents:
diff changeset
296 /* Worker for ipa_propagate_frequency_1. */
kono
parents:
diff changeset
297
kono
parents:
diff changeset
298 static bool
kono
parents:
diff changeset
299 ipa_propagate_frequency_1 (struct cgraph_node *node, void *data)
kono
parents:
diff changeset
300 {
kono
parents:
diff changeset
301 struct ipa_propagate_frequency_data *d;
kono
parents:
diff changeset
302 struct cgraph_edge *edge;
kono
parents:
diff changeset
303
kono
parents:
diff changeset
304 d = (struct ipa_propagate_frequency_data *)data;
kono
parents:
diff changeset
305 for (edge = node->callers;
kono
parents:
diff changeset
306 edge && (d->maybe_unlikely_executed || d->maybe_executed_once
kono
parents:
diff changeset
307 || d->only_called_at_startup || d->only_called_at_exit);
kono
parents:
diff changeset
308 edge = edge->next_caller)
kono
parents:
diff changeset
309 {
kono
parents:
diff changeset
310 if (edge->caller != d->function_symbol)
kono
parents:
diff changeset
311 {
kono
parents:
diff changeset
312 d->only_called_at_startup &= edge->caller->only_called_at_startup;
kono
parents:
diff changeset
313 /* It makes sense to put main() together with the static constructors.
kono
parents:
diff changeset
314 It will be executed for sure, but rest of functions called from
kono
parents:
diff changeset
315 main are definitely not at startup only. */
kono
parents:
diff changeset
316 if (MAIN_NAME_P (DECL_NAME (edge->caller->decl)))
kono
parents:
diff changeset
317 d->only_called_at_startup = 0;
kono
parents:
diff changeset
318 d->only_called_at_exit &= edge->caller->only_called_at_exit;
kono
parents:
diff changeset
319 }
kono
parents:
diff changeset
320
kono
parents:
diff changeset
321 /* When profile feedback is available, do not try to propagate too hard;
kono
parents:
diff changeset
322 counts are already good guide on function frequencies and roundoff
kono
parents:
diff changeset
323 errors can make us to push function into unlikely section even when
kono
parents:
diff changeset
324 it is executed by the train run. Transfer the function only if all
kono
parents:
diff changeset
325 callers are unlikely executed. */
kono
parents:
diff changeset
326 if (profile_info
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
327 && !(edge->callee->count.ipa () == profile_count::zero ())
111
kono
parents:
diff changeset
328 && (edge->caller->frequency != NODE_FREQUENCY_UNLIKELY_EXECUTED
kono
parents:
diff changeset
329 || (edge->caller->global.inlined_to
kono
parents:
diff changeset
330 && edge->caller->global.inlined_to->frequency
kono
parents:
diff changeset
331 != NODE_FREQUENCY_UNLIKELY_EXECUTED)))
kono
parents:
diff changeset
332 d->maybe_unlikely_executed = false;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
333 if (edge->count.ipa ().initialized_p ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
334 && !edge->count.ipa ().nonzero_p ())
111
kono
parents:
diff changeset
335 continue;
kono
parents:
diff changeset
336 switch (edge->caller->frequency)
kono
parents:
diff changeset
337 {
kono
parents:
diff changeset
338 case NODE_FREQUENCY_UNLIKELY_EXECUTED:
kono
parents:
diff changeset
339 break;
kono
parents:
diff changeset
340 case NODE_FREQUENCY_EXECUTED_ONCE:
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
341 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
342 if (dump_file && (dump_flags & TDF_DETAILS))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
343 fprintf (dump_file, " Called by %s that is executed once\n",
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
344 edge->caller->name ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
345 d->maybe_unlikely_executed = false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
346 ipa_call_summary *s = ipa_call_summaries->get (edge);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
347 if (s != NULL && s->loop_depth)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
348 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
349 d->maybe_executed_once = false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
350 if (dump_file && (dump_flags & TDF_DETAILS))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
351 fprintf (dump_file, " Called in loop\n");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
352 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
353 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
354 }
111
kono
parents:
diff changeset
355 case NODE_FREQUENCY_HOT:
kono
parents:
diff changeset
356 case NODE_FREQUENCY_NORMAL:
kono
parents:
diff changeset
357 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
358 fprintf (dump_file, " Called by %s that is normal or hot\n",
kono
parents:
diff changeset
359 edge->caller->name ());
kono
parents:
diff changeset
360 d->maybe_unlikely_executed = false;
kono
parents:
diff changeset
361 d->maybe_executed_once = false;
kono
parents:
diff changeset
362 break;
kono
parents:
diff changeset
363 }
kono
parents:
diff changeset
364 }
kono
parents:
diff changeset
365 return edge != NULL;
kono
parents:
diff changeset
366 }
kono
parents:
diff changeset
367
kono
parents:
diff changeset
368 /* Return ture if NODE contains hot calls. */
kono
parents:
diff changeset
369
kono
parents:
diff changeset
370 bool
kono
parents:
diff changeset
371 contains_hot_call_p (struct cgraph_node *node)
kono
parents:
diff changeset
372 {
kono
parents:
diff changeset
373 struct cgraph_edge *e;
kono
parents:
diff changeset
374 for (e = node->callees; e; e = e->next_callee)
kono
parents:
diff changeset
375 if (e->maybe_hot_p ())
kono
parents:
diff changeset
376 return true;
kono
parents:
diff changeset
377 else if (!e->inline_failed
kono
parents:
diff changeset
378 && contains_hot_call_p (e->callee))
kono
parents:
diff changeset
379 return true;
kono
parents:
diff changeset
380 for (e = node->indirect_calls; e; e = e->next_callee)
kono
parents:
diff changeset
381 if (e->maybe_hot_p ())
kono
parents:
diff changeset
382 return true;
kono
parents:
diff changeset
383 return false;
kono
parents:
diff changeset
384 }
kono
parents:
diff changeset
385
kono
parents:
diff changeset
386 /* See if the frequency of NODE can be updated based on frequencies of its
kono
parents:
diff changeset
387 callers. */
kono
parents:
diff changeset
388 bool
kono
parents:
diff changeset
389 ipa_propagate_frequency (struct cgraph_node *node)
kono
parents:
diff changeset
390 {
kono
parents:
diff changeset
391 struct ipa_propagate_frequency_data d = {node, true, true, true, true};
kono
parents:
diff changeset
392 bool changed = false;
kono
parents:
diff changeset
393
kono
parents:
diff changeset
394 /* We can not propagate anything useful about externally visible functions
kono
parents:
diff changeset
395 nor about virtuals. */
kono
parents:
diff changeset
396 if (!node->local.local
kono
parents:
diff changeset
397 || node->alias
kono
parents:
diff changeset
398 || (opt_for_fn (node->decl, flag_devirtualize)
kono
parents:
diff changeset
399 && DECL_VIRTUAL_P (node->decl)))
kono
parents:
diff changeset
400 return false;
kono
parents:
diff changeset
401 gcc_assert (node->analyzed);
kono
parents:
diff changeset
402 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
403 fprintf (dump_file, "Processing frequency %s\n", node->name ());
kono
parents:
diff changeset
404
kono
parents:
diff changeset
405 node->call_for_symbol_and_aliases (ipa_propagate_frequency_1, &d,
kono
parents:
diff changeset
406 true);
kono
parents:
diff changeset
407
kono
parents:
diff changeset
408 if ((d.only_called_at_startup && !d.only_called_at_exit)
kono
parents:
diff changeset
409 && !node->only_called_at_startup)
kono
parents:
diff changeset
410 {
kono
parents:
diff changeset
411 node->only_called_at_startup = true;
kono
parents:
diff changeset
412 if (dump_file)
kono
parents:
diff changeset
413 fprintf (dump_file, "Node %s promoted to only called at startup.\n",
kono
parents:
diff changeset
414 node->name ());
kono
parents:
diff changeset
415 changed = true;
kono
parents:
diff changeset
416 }
kono
parents:
diff changeset
417 if ((d.only_called_at_exit && !d.only_called_at_startup)
kono
parents:
diff changeset
418 && !node->only_called_at_exit)
kono
parents:
diff changeset
419 {
kono
parents:
diff changeset
420 node->only_called_at_exit = true;
kono
parents:
diff changeset
421 if (dump_file)
kono
parents:
diff changeset
422 fprintf (dump_file, "Node %s promoted to only called at exit.\n",
kono
parents:
diff changeset
423 node->name ());
kono
parents:
diff changeset
424 changed = true;
kono
parents:
diff changeset
425 }
kono
parents:
diff changeset
426
kono
parents:
diff changeset
427 /* With profile we can decide on hot/normal based on count. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
428 if (node->count. ipa().initialized_p ())
111
kono
parents:
diff changeset
429 {
kono
parents:
diff changeset
430 bool hot = false;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
431 if (!(node->count. ipa() == profile_count::zero ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
432 && node->count. ipa() >= get_hot_bb_threshold ())
111
kono
parents:
diff changeset
433 hot = true;
kono
parents:
diff changeset
434 if (!hot)
kono
parents:
diff changeset
435 hot |= contains_hot_call_p (node);
kono
parents:
diff changeset
436 if (hot)
kono
parents:
diff changeset
437 {
kono
parents:
diff changeset
438 if (node->frequency != NODE_FREQUENCY_HOT)
kono
parents:
diff changeset
439 {
kono
parents:
diff changeset
440 if (dump_file)
kono
parents:
diff changeset
441 fprintf (dump_file, "Node %s promoted to hot.\n",
kono
parents:
diff changeset
442 node->name ());
kono
parents:
diff changeset
443 node->frequency = NODE_FREQUENCY_HOT;
kono
parents:
diff changeset
444 return true;
kono
parents:
diff changeset
445 }
kono
parents:
diff changeset
446 return false;
kono
parents:
diff changeset
447 }
kono
parents:
diff changeset
448 else if (node->frequency == NODE_FREQUENCY_HOT)
kono
parents:
diff changeset
449 {
kono
parents:
diff changeset
450 if (dump_file)
kono
parents:
diff changeset
451 fprintf (dump_file, "Node %s reduced to normal.\n",
kono
parents:
diff changeset
452 node->name ());
kono
parents:
diff changeset
453 node->frequency = NODE_FREQUENCY_NORMAL;
kono
parents:
diff changeset
454 changed = true;
kono
parents:
diff changeset
455 }
kono
parents:
diff changeset
456 }
kono
parents:
diff changeset
457 /* These come either from profile or user hints; never update them. */
kono
parents:
diff changeset
458 if (node->frequency == NODE_FREQUENCY_HOT
kono
parents:
diff changeset
459 || node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
kono
parents:
diff changeset
460 return changed;
kono
parents:
diff changeset
461 if (d.maybe_unlikely_executed)
kono
parents:
diff changeset
462 {
kono
parents:
diff changeset
463 node->frequency = NODE_FREQUENCY_UNLIKELY_EXECUTED;
kono
parents:
diff changeset
464 if (dump_file)
kono
parents:
diff changeset
465 fprintf (dump_file, "Node %s promoted to unlikely executed.\n",
kono
parents:
diff changeset
466 node->name ());
kono
parents:
diff changeset
467 changed = true;
kono
parents:
diff changeset
468 }
kono
parents:
diff changeset
469 else if (d.maybe_executed_once && node->frequency != NODE_FREQUENCY_EXECUTED_ONCE)
kono
parents:
diff changeset
470 {
kono
parents:
diff changeset
471 node->frequency = NODE_FREQUENCY_EXECUTED_ONCE;
kono
parents:
diff changeset
472 if (dump_file)
kono
parents:
diff changeset
473 fprintf (dump_file, "Node %s promoted to executed once.\n",
kono
parents:
diff changeset
474 node->name ());
kono
parents:
diff changeset
475 changed = true;
kono
parents:
diff changeset
476 }
kono
parents:
diff changeset
477 return changed;
kono
parents:
diff changeset
478 }
kono
parents:
diff changeset
479
kono
parents:
diff changeset
480 /* Simple ipa profile pass propagating frequencies across the callgraph. */
kono
parents:
diff changeset
481
kono
parents:
diff changeset
482 static unsigned int
kono
parents:
diff changeset
483 ipa_profile (void)
kono
parents:
diff changeset
484 {
kono
parents:
diff changeset
485 struct cgraph_node **order;
kono
parents:
diff changeset
486 struct cgraph_edge *e;
kono
parents:
diff changeset
487 int order_pos;
kono
parents:
diff changeset
488 bool something_changed = false;
kono
parents:
diff changeset
489 int i;
kono
parents:
diff changeset
490 gcov_type overall_time = 0, cutoff = 0, cumulated = 0, overall_size = 0;
kono
parents:
diff changeset
491 struct cgraph_node *n,*n2;
kono
parents:
diff changeset
492 int nindirect = 0, ncommon = 0, nunknown = 0, nuseless = 0, nconverted = 0;
kono
parents:
diff changeset
493 int nmismatch = 0, nimpossible = 0;
kono
parents:
diff changeset
494 bool node_map_initialized = false;
kono
parents:
diff changeset
495
kono
parents:
diff changeset
496 if (dump_file)
kono
parents:
diff changeset
497 dump_histogram (dump_file, histogram);
kono
parents:
diff changeset
498 for (i = 0; i < (int)histogram.length (); i++)
kono
parents:
diff changeset
499 {
kono
parents:
diff changeset
500 overall_time += histogram[i]->count * histogram[i]->time;
kono
parents:
diff changeset
501 overall_size += histogram[i]->size;
kono
parents:
diff changeset
502 }
kono
parents:
diff changeset
503 if (overall_time)
kono
parents:
diff changeset
504 {
kono
parents:
diff changeset
505 gcov_type threshold;
kono
parents:
diff changeset
506
kono
parents:
diff changeset
507 gcc_assert (overall_size);
kono
parents:
diff changeset
508
kono
parents:
diff changeset
509 cutoff = (overall_time * PARAM_VALUE (HOT_BB_COUNT_WS_PERMILLE) + 500) / 1000;
kono
parents:
diff changeset
510 threshold = 0;
kono
parents:
diff changeset
511 for (i = 0; cumulated < cutoff; i++)
kono
parents:
diff changeset
512 {
kono
parents:
diff changeset
513 cumulated += histogram[i]->count * histogram[i]->time;
kono
parents:
diff changeset
514 threshold = histogram[i]->count;
kono
parents:
diff changeset
515 }
kono
parents:
diff changeset
516 if (!threshold)
kono
parents:
diff changeset
517 threshold = 1;
kono
parents:
diff changeset
518 if (dump_file)
kono
parents:
diff changeset
519 {
kono
parents:
diff changeset
520 gcov_type cumulated_time = 0, cumulated_size = 0;
kono
parents:
diff changeset
521
kono
parents:
diff changeset
522 for (i = 0;
kono
parents:
diff changeset
523 i < (int)histogram.length () && histogram[i]->count >= threshold;
kono
parents:
diff changeset
524 i++)
kono
parents:
diff changeset
525 {
kono
parents:
diff changeset
526 cumulated_time += histogram[i]->count * histogram[i]->time;
kono
parents:
diff changeset
527 cumulated_size += histogram[i]->size;
kono
parents:
diff changeset
528 }
kono
parents:
diff changeset
529 fprintf (dump_file, "Determined min count: %" PRId64
kono
parents:
diff changeset
530 " Time:%3.2f%% Size:%3.2f%%\n",
kono
parents:
diff changeset
531 (int64_t)threshold,
kono
parents:
diff changeset
532 cumulated_time * 100.0 / overall_time,
kono
parents:
diff changeset
533 cumulated_size * 100.0 / overall_size);
kono
parents:
diff changeset
534 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
535
111
kono
parents:
diff changeset
536 if (threshold > get_hot_bb_threshold ()
kono
parents:
diff changeset
537 || in_lto_p)
kono
parents:
diff changeset
538 {
kono
parents:
diff changeset
539 if (dump_file)
kono
parents:
diff changeset
540 fprintf (dump_file, "Threshold updated.\n");
kono
parents:
diff changeset
541 set_hot_bb_threshold (threshold);
kono
parents:
diff changeset
542 }
kono
parents:
diff changeset
543 }
kono
parents:
diff changeset
544 histogram.release ();
kono
parents:
diff changeset
545 histogram_pool.release ();
kono
parents:
diff changeset
546
kono
parents:
diff changeset
547 /* Produce speculative calls: we saved common traget from porfiling into
kono
parents:
diff changeset
548 e->common_target_id. Now, at link time, we can look up corresponding
kono
parents:
diff changeset
549 function node and produce speculative call. */
kono
parents:
diff changeset
550
kono
parents:
diff changeset
551 FOR_EACH_DEFINED_FUNCTION (n)
kono
parents:
diff changeset
552 {
kono
parents:
diff changeset
553 bool update = false;
kono
parents:
diff changeset
554
kono
parents:
diff changeset
555 if (!opt_for_fn (n->decl, flag_ipa_profile))
kono
parents:
diff changeset
556 continue;
kono
parents:
diff changeset
557
kono
parents:
diff changeset
558 for (e = n->indirect_calls; e; e = e->next_callee)
kono
parents:
diff changeset
559 {
kono
parents:
diff changeset
560 if (n->count.initialized_p ())
kono
parents:
diff changeset
561 nindirect++;
kono
parents:
diff changeset
562 if (e->indirect_info->common_target_id)
kono
parents:
diff changeset
563 {
kono
parents:
diff changeset
564 if (!node_map_initialized)
kono
parents:
diff changeset
565 init_node_map (false);
kono
parents:
diff changeset
566 node_map_initialized = true;
kono
parents:
diff changeset
567 ncommon++;
kono
parents:
diff changeset
568 n2 = find_func_by_profile_id (e->indirect_info->common_target_id);
kono
parents:
diff changeset
569 if (n2)
kono
parents:
diff changeset
570 {
kono
parents:
diff changeset
571 if (dump_file)
kono
parents:
diff changeset
572 {
kono
parents:
diff changeset
573 fprintf (dump_file, "Indirect call -> direct call from"
kono
parents:
diff changeset
574 " other module %s => %s, prob %3.2f\n",
kono
parents:
diff changeset
575 n->dump_name (),
kono
parents:
diff changeset
576 n2->dump_name (),
kono
parents:
diff changeset
577 e->indirect_info->common_target_probability
kono
parents:
diff changeset
578 / (float)REG_BR_PROB_BASE);
kono
parents:
diff changeset
579 }
kono
parents:
diff changeset
580 if (e->indirect_info->common_target_probability
kono
parents:
diff changeset
581 < REG_BR_PROB_BASE / 2)
kono
parents:
diff changeset
582 {
kono
parents:
diff changeset
583 nuseless++;
kono
parents:
diff changeset
584 if (dump_file)
kono
parents:
diff changeset
585 fprintf (dump_file,
kono
parents:
diff changeset
586 "Not speculating: probability is too low.\n");
kono
parents:
diff changeset
587 }
kono
parents:
diff changeset
588 else if (!e->maybe_hot_p ())
kono
parents:
diff changeset
589 {
kono
parents:
diff changeset
590 nuseless++;
kono
parents:
diff changeset
591 if (dump_file)
kono
parents:
diff changeset
592 fprintf (dump_file,
kono
parents:
diff changeset
593 "Not speculating: call is cold.\n");
kono
parents:
diff changeset
594 }
kono
parents:
diff changeset
595 else if (n2->get_availability () <= AVAIL_INTERPOSABLE
kono
parents:
diff changeset
596 && n2->can_be_discarded_p ())
kono
parents:
diff changeset
597 {
kono
parents:
diff changeset
598 nuseless++;
kono
parents:
diff changeset
599 if (dump_file)
kono
parents:
diff changeset
600 fprintf (dump_file,
kono
parents:
diff changeset
601 "Not speculating: target is overwritable "
kono
parents:
diff changeset
602 "and can be discarded.\n");
kono
parents:
diff changeset
603 }
kono
parents:
diff changeset
604 else if (ipa_node_params_sum && ipa_edge_args_sum
kono
parents:
diff changeset
605 && (!vec_safe_is_empty
kono
parents:
diff changeset
606 (IPA_NODE_REF (n2)->descriptors))
kono
parents:
diff changeset
607 && ipa_get_param_count (IPA_NODE_REF (n2))
kono
parents:
diff changeset
608 != ipa_get_cs_argument_count (IPA_EDGE_REF (e))
kono
parents:
diff changeset
609 && (ipa_get_param_count (IPA_NODE_REF (n2))
kono
parents:
diff changeset
610 >= ipa_get_cs_argument_count (IPA_EDGE_REF (e))
kono
parents:
diff changeset
611 || !stdarg_p (TREE_TYPE (n2->decl))))
kono
parents:
diff changeset
612 {
kono
parents:
diff changeset
613 nmismatch++;
kono
parents:
diff changeset
614 if (dump_file)
kono
parents:
diff changeset
615 fprintf (dump_file,
kono
parents:
diff changeset
616 "Not speculating: "
kono
parents:
diff changeset
617 "parameter count mistmatch\n");
kono
parents:
diff changeset
618 }
kono
parents:
diff changeset
619 else if (e->indirect_info->polymorphic
kono
parents:
diff changeset
620 && !opt_for_fn (n->decl, flag_devirtualize)
kono
parents:
diff changeset
621 && !possible_polymorphic_call_target_p (e, n2))
kono
parents:
diff changeset
622 {
kono
parents:
diff changeset
623 nimpossible++;
kono
parents:
diff changeset
624 if (dump_file)
kono
parents:
diff changeset
625 fprintf (dump_file,
kono
parents:
diff changeset
626 "Not speculating: "
kono
parents:
diff changeset
627 "function is not in the polymorphic "
kono
parents:
diff changeset
628 "call target list\n");
kono
parents:
diff changeset
629 }
kono
parents:
diff changeset
630 else
kono
parents:
diff changeset
631 {
kono
parents:
diff changeset
632 /* Target may be overwritable, but profile says that
kono
parents:
diff changeset
633 control flow goes to this particular implementation
kono
parents:
diff changeset
634 of N2. Speculate on the local alias to allow inlining.
kono
parents:
diff changeset
635 */
kono
parents:
diff changeset
636 if (!n2->can_be_discarded_p ())
kono
parents:
diff changeset
637 {
kono
parents:
diff changeset
638 cgraph_node *alias;
kono
parents:
diff changeset
639 alias = dyn_cast<cgraph_node *> (n2->noninterposable_alias ());
kono
parents:
diff changeset
640 if (alias)
kono
parents:
diff changeset
641 n2 = alias;
kono
parents:
diff changeset
642 }
kono
parents:
diff changeset
643 nconverted++;
kono
parents:
diff changeset
644 e->make_speculative
kono
parents:
diff changeset
645 (n2,
kono
parents:
diff changeset
646 e->count.apply_probability
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
647 (e->indirect_info->common_target_probability));
111
kono
parents:
diff changeset
648 update = true;
kono
parents:
diff changeset
649 }
kono
parents:
diff changeset
650 }
kono
parents:
diff changeset
651 else
kono
parents:
diff changeset
652 {
kono
parents:
diff changeset
653 if (dump_file)
kono
parents:
diff changeset
654 fprintf (dump_file, "Function with profile-id %i not found.\n",
kono
parents:
diff changeset
655 e->indirect_info->common_target_id);
kono
parents:
diff changeset
656 nunknown++;
kono
parents:
diff changeset
657 }
kono
parents:
diff changeset
658 }
kono
parents:
diff changeset
659 }
kono
parents:
diff changeset
660 if (update)
kono
parents:
diff changeset
661 ipa_update_overall_fn_summary (n);
kono
parents:
diff changeset
662 }
kono
parents:
diff changeset
663 if (node_map_initialized)
kono
parents:
diff changeset
664 del_node_map ();
kono
parents:
diff changeset
665 if (dump_file && nindirect)
kono
parents:
diff changeset
666 fprintf (dump_file,
kono
parents:
diff changeset
667 "%i indirect calls trained.\n"
kono
parents:
diff changeset
668 "%i (%3.2f%%) have common target.\n"
kono
parents:
diff changeset
669 "%i (%3.2f%%) targets was not found.\n"
kono
parents:
diff changeset
670 "%i (%3.2f%%) targets had parameter count mismatch.\n"
kono
parents:
diff changeset
671 "%i (%3.2f%%) targets was not in polymorphic call target list.\n"
kono
parents:
diff changeset
672 "%i (%3.2f%%) speculations seems useless.\n"
kono
parents:
diff changeset
673 "%i (%3.2f%%) speculations produced.\n",
kono
parents:
diff changeset
674 nindirect,
kono
parents:
diff changeset
675 ncommon, ncommon * 100.0 / nindirect,
kono
parents:
diff changeset
676 nunknown, nunknown * 100.0 / nindirect,
kono
parents:
diff changeset
677 nmismatch, nmismatch * 100.0 / nindirect,
kono
parents:
diff changeset
678 nimpossible, nimpossible * 100.0 / nindirect,
kono
parents:
diff changeset
679 nuseless, nuseless * 100.0 / nindirect,
kono
parents:
diff changeset
680 nconverted, nconverted * 100.0 / nindirect);
kono
parents:
diff changeset
681
kono
parents:
diff changeset
682 order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
kono
parents:
diff changeset
683 order_pos = ipa_reverse_postorder (order);
kono
parents:
diff changeset
684 for (i = order_pos - 1; i >= 0; i--)
kono
parents:
diff changeset
685 {
kono
parents:
diff changeset
686 if (order[i]->local.local
kono
parents:
diff changeset
687 && opt_for_fn (order[i]->decl, flag_ipa_profile)
kono
parents:
diff changeset
688 && ipa_propagate_frequency (order[i]))
kono
parents:
diff changeset
689 {
kono
parents:
diff changeset
690 for (e = order[i]->callees; e; e = e->next_callee)
kono
parents:
diff changeset
691 if (e->callee->local.local && !e->callee->aux)
kono
parents:
diff changeset
692 {
kono
parents:
diff changeset
693 something_changed = true;
kono
parents:
diff changeset
694 e->callee->aux = (void *)1;
kono
parents:
diff changeset
695 }
kono
parents:
diff changeset
696 }
kono
parents:
diff changeset
697 order[i]->aux = NULL;
kono
parents:
diff changeset
698 }
kono
parents:
diff changeset
699
kono
parents:
diff changeset
700 while (something_changed)
kono
parents:
diff changeset
701 {
kono
parents:
diff changeset
702 something_changed = false;
kono
parents:
diff changeset
703 for (i = order_pos - 1; i >= 0; i--)
kono
parents:
diff changeset
704 {
kono
parents:
diff changeset
705 if (order[i]->aux
kono
parents:
diff changeset
706 && opt_for_fn (order[i]->decl, flag_ipa_profile)
kono
parents:
diff changeset
707 && ipa_propagate_frequency (order[i]))
kono
parents:
diff changeset
708 {
kono
parents:
diff changeset
709 for (e = order[i]->callees; e; e = e->next_callee)
kono
parents:
diff changeset
710 if (e->callee->local.local && !e->callee->aux)
kono
parents:
diff changeset
711 {
kono
parents:
diff changeset
712 something_changed = true;
kono
parents:
diff changeset
713 e->callee->aux = (void *)1;
kono
parents:
diff changeset
714 }
kono
parents:
diff changeset
715 }
kono
parents:
diff changeset
716 order[i]->aux = NULL;
kono
parents:
diff changeset
717 }
kono
parents:
diff changeset
718 }
kono
parents:
diff changeset
719 free (order);
kono
parents:
diff changeset
720 return 0;
kono
parents:
diff changeset
721 }
kono
parents:
diff changeset
722
kono
parents:
diff changeset
723 namespace {
kono
parents:
diff changeset
724
kono
parents:
diff changeset
725 const pass_data pass_data_ipa_profile =
kono
parents:
diff changeset
726 {
kono
parents:
diff changeset
727 IPA_PASS, /* type */
kono
parents:
diff changeset
728 "profile_estimate", /* name */
kono
parents:
diff changeset
729 OPTGROUP_NONE, /* optinfo_flags */
kono
parents:
diff changeset
730 TV_IPA_PROFILE, /* tv_id */
kono
parents:
diff changeset
731 0, /* properties_required */
kono
parents:
diff changeset
732 0, /* properties_provided */
kono
parents:
diff changeset
733 0, /* properties_destroyed */
kono
parents:
diff changeset
734 0, /* todo_flags_start */
kono
parents:
diff changeset
735 0, /* todo_flags_finish */
kono
parents:
diff changeset
736 };
kono
parents:
diff changeset
737
kono
parents:
diff changeset
738 class pass_ipa_profile : public ipa_opt_pass_d
kono
parents:
diff changeset
739 {
kono
parents:
diff changeset
740 public:
kono
parents:
diff changeset
741 pass_ipa_profile (gcc::context *ctxt)
kono
parents:
diff changeset
742 : ipa_opt_pass_d (pass_data_ipa_profile, ctxt,
kono
parents:
diff changeset
743 ipa_profile_generate_summary, /* generate_summary */
kono
parents:
diff changeset
744 ipa_profile_write_summary, /* write_summary */
kono
parents:
diff changeset
745 ipa_profile_read_summary, /* read_summary */
kono
parents:
diff changeset
746 NULL, /* write_optimization_summary */
kono
parents:
diff changeset
747 NULL, /* read_optimization_summary */
kono
parents:
diff changeset
748 NULL, /* stmt_fixup */
kono
parents:
diff changeset
749 0, /* function_transform_todo_flags_start */
kono
parents:
diff changeset
750 NULL, /* function_transform */
kono
parents:
diff changeset
751 NULL) /* variable_transform */
kono
parents:
diff changeset
752 {}
kono
parents:
diff changeset
753
kono
parents:
diff changeset
754 /* opt_pass methods: */
kono
parents:
diff changeset
755 virtual bool gate (function *) { return flag_ipa_profile || in_lto_p; }
kono
parents:
diff changeset
756 virtual unsigned int execute (function *) { return ipa_profile (); }
kono
parents:
diff changeset
757
kono
parents:
diff changeset
758 }; // class pass_ipa_profile
kono
parents:
diff changeset
759
kono
parents:
diff changeset
760 } // anon namespace
kono
parents:
diff changeset
761
kono
parents:
diff changeset
762 ipa_opt_pass_d *
kono
parents:
diff changeset
763 make_pass_ipa_profile (gcc::context *ctxt)
kono
parents:
diff changeset
764 {
kono
parents:
diff changeset
765 return new pass_ipa_profile (ctxt);
kono
parents:
diff changeset
766 }