annotate gcc/ipa-profile.c @ 128:fe568345ddd5

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