Branch data Line data Source code
1 : : /* Read and annotate call graph profile from the auto profile data file.
2 : : Copyright (C) 2014-2025 Free Software Foundation, Inc.
3 : : Contributed by Dehao Chen (dehao@google.com)
4 : :
5 : : This file is part of GCC.
6 : :
7 : : GCC is free software; you can redistribute it and/or modify it under
8 : : the terms of the GNU General Public License as published by the Free
9 : : Software Foundation; either version 3, or (at your option) any later
10 : : version.
11 : :
12 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 : : for more details.
16 : :
17 : : You should have received a copy of the GNU General Public License
18 : : along with GCC; see the file COPYING3. If not see
19 : : <http://www.gnu.org/licenses/>. */
20 : :
21 : : #include "config.h"
22 : : #define INCLUDE_MAP
23 : : #define INCLUDE_SET
24 : : #include "system.h"
25 : : #include "coretypes.h"
26 : : #include "backend.h"
27 : : #include "tree.h"
28 : : #include "gimple.h"
29 : : #include "predict.h"
30 : : #include "alloc-pool.h"
31 : : #include "tree-pass.h"
32 : : #include "ssa.h"
33 : : #include "cgraph.h"
34 : : #include "gcov-io.h"
35 : : #include "diagnostic-core.h"
36 : : #include "profile.h"
37 : : #include "langhooks.h"
38 : : #include "context.h"
39 : : #include "pass_manager.h"
40 : : #include "cfgloop.h"
41 : : #include "tree-cfg.h"
42 : : #include "tree-cfgcleanup.h"
43 : : #include "tree-into-ssa.h"
44 : : #include "gimple-iterator.h"
45 : : #include "value-prof.h"
46 : : #include "symbol-summary.h"
47 : : #include "sreal.h"
48 : : #include "ipa-cp.h"
49 : : #include "ipa-prop.h"
50 : : #include "ipa-fnsummary.h"
51 : : #include "ipa-inline.h"
52 : : #include "tree-inline.h"
53 : : #include "auto-profile.h"
54 : : #include "tree-pretty-print.h"
55 : : #include "gimple-pretty-print.h"
56 : :
57 : : /* The following routines implements AutoFDO optimization.
58 : :
59 : : This optimization uses sampling profiles to annotate basic block counts
60 : : and uses heuristics to estimate branch probabilities.
61 : :
62 : : There are three phases in AutoFDO:
63 : :
64 : : Phase 1: Read profile from the profile data file.
65 : : The following info is read from the profile datafile:
66 : : * string_table: a map between function name and its index.
67 : : * autofdo_source_profile: a map from function_instance name to
68 : : function_instance. This is represented as a forest of
69 : : function_instances.
70 : : * WorkingSet: a histogram of how many instructions are covered for a
71 : : given percentage of total cycles. This is describing the binary
72 : : level information (not source level). This info is used to help
73 : : decide if we want aggressive optimizations that could increase
74 : : code footprint (e.g. loop unroll etc.)
75 : : A function instance is an instance of function that could either be a
76 : : standalone symbol, or a clone of a function that is inlined into another
77 : : function.
78 : :
79 : : Phase 2: Early inline + value profile transformation.
80 : : Early inline uses autofdo_source_profile to find if a callsite is:
81 : : * inlined in the profiled binary.
82 : : * callee body is hot in the profiling run.
83 : : If both condition satisfies, early inline will inline the callsite
84 : : regardless of the code growth.
85 : : Phase 2 is an iterative process. During each iteration, we also check
86 : : if an indirect callsite is promoted and inlined in the profiling run.
87 : : If yes, vpt will happen to force promote it and in the next iteration,
88 : : einline will inline the promoted callsite in the next iteration.
89 : :
90 : : Phase 3: Annotate control flow graph.
91 : : AutoFDO uses a separate pass to:
92 : : * Annotate basic block count
93 : : * Estimate branch probability
94 : :
95 : : After the above 3 phases, all profile is readily annotated on the GCC IR.
96 : : AutoFDO tries to reuse all FDO infrastructure as much as possible to make
97 : : use of the profile. E.g. it uses existing mechanism to calculate the basic
98 : : block/edge frequency, as well as the cgraph node/edge count.
99 : : */
100 : :
101 : : #define DEFAULT_AUTO_PROFILE_FILE "fbdata.afdo"
102 : : #define AUTO_PROFILE_VERSION 2
103 : :
104 : : namespace autofdo
105 : : {
106 : :
107 : : /* Intermediate edge info used when propagating AutoFDO profile information.
108 : : We can't edge->count() directly since it's computed from edge's probability
109 : : while probability is yet not decided during propagation. */
110 : : #define AFDO_EINFO(e) ((class edge_info *) e->aux)
111 : : class edge_info
112 : : {
113 : : public:
114 : 0 : edge_info () : count_ (profile_count::zero ().afdo ()), annotated_ (false) {}
115 : 0 : bool is_annotated () const { return annotated_; }
116 : 0 : void set_annotated () { annotated_ = true; }
117 : 0 : profile_count get_count () const { return count_; }
118 : 0 : void set_count (profile_count count) { count_ = count; }
119 : : private:
120 : : profile_count count_;
121 : : bool annotated_;
122 : : };
123 : :
124 : : /* Represent a source location: (function_decl, lineno). */
125 : : typedef std::pair<tree, unsigned> decl_lineno;
126 : :
127 : : /* Represent an inline stack. vector[0] is the leaf node. */
128 : : typedef auto_vec<decl_lineno> inline_stack;
129 : :
130 : : /* String array that stores function names. */
131 : : typedef auto_vec<char *> string_vector;
132 : :
133 : : /* Map from function name's index in string_table to target's
134 : : execution count. */
135 : : typedef std::map<unsigned, gcov_type> icall_target_map;
136 : :
137 : : /* Set of gimple stmts. Used to track if the stmt has already been promoted
138 : : to direct call. */
139 : : typedef std::set<gimple *> stmt_set;
140 : :
141 : : /* Represent count info of an inline stack. */
142 : 0 : class count_info
143 : : {
144 : : public:
145 : : /* Sampled count of the inline stack. */
146 : : gcov_type count;
147 : :
148 : : /* Map from indirect call target to its sample count. */
149 : : icall_target_map targets;
150 : :
151 : : /* Whether this inline stack is already used in annotation.
152 : :
153 : : Each inline stack should only be used to annotate IR once.
154 : : This will be enforced when instruction-level discriminator
155 : : is supported. */
156 : : };
157 : :
158 : : /* operator< for "const char *". */
159 : : struct string_compare
160 : : {
161 : 0 : bool operator()(const char *a, const char *b) const
162 : : {
163 : 0 : return strcmp (a, b) < 0;
164 : : }
165 : : };
166 : :
167 : : /* Store a string array, indexed by string position in the array. */
168 : : class string_table
169 : : {
170 : : public:
171 : 0 : string_table ()
172 : 0 : {}
173 : :
174 : : ~string_table ();
175 : :
176 : : /* For a given string, returns its index. */
177 : : int get_index (const char *name) const;
178 : :
179 : : /* For a given decl, returns the index of the decl name. */
180 : : int get_index_by_decl (tree decl) const;
181 : :
182 : : /* For a given index, returns the string. */
183 : : const char *get_name (int index) const;
184 : :
185 : : /* Read profile, return TRUE on success. */
186 : : bool read ();
187 : :
188 : : private:
189 : : typedef std::map<const char *, unsigned, string_compare> string_index_map;
190 : : string_vector vector_;
191 : : string_index_map map_;
192 : : };
193 : :
194 : : /* Profile of a function instance:
195 : : 1. total_count of the function.
196 : : 2. head_count (entry basic block count) of the function (only valid when
197 : : function is a top-level function_instance, i.e. it is the original copy
198 : : instead of the inlined copy).
199 : : 3. map from source location (decl_lineno) to profile (count_info).
200 : : 4. map from callsite to callee function_instance. */
201 : : class function_instance
202 : : {
203 : : public:
204 : : typedef auto_vec<function_instance *> function_instance_stack;
205 : :
206 : : /* Read the profile and return a function_instance with head count as
207 : : HEAD_COUNT. Recursively read callsites to create nested function_instances
208 : : too. STACK is used to track the recursive creation process. */
209 : : static function_instance *
210 : : read_function_instance (function_instance_stack *stack,
211 : : gcov_type head_count);
212 : :
213 : : /* Recursively deallocate all callsites (nested function_instances). */
214 : : ~function_instance ();
215 : :
216 : : /* Accessors. */
217 : : int
218 : 0 : name () const
219 : : {
220 : 0 : return name_;
221 : : }
222 : : gcov_type
223 : 0 : total_count () const
224 : : {
225 : 0 : return total_count_;
226 : : }
227 : : gcov_type
228 : 0 : head_count () const
229 : : {
230 : 0 : return head_count_;
231 : : }
232 : :
233 : : /* Traverse callsites of the current function_instance to find one at the
234 : : location of LINENO and callee name represented in DECL. */
235 : : function_instance *get_function_instance_by_decl (unsigned lineno,
236 : : tree decl) const;
237 : :
238 : : /* Merge profile of clones. Note that cloning hasnt been performed when
239 : : we annotate the CFG (at this stage). */
240 : : void merge (function_instance *other);
241 : :
242 : : /* Store the profile info for LOC in INFO. Return TRUE if profile info
243 : : is found. */
244 : : bool get_count_info (location_t loc, count_info *info) const;
245 : :
246 : : /* Read the inlined indirect call target profile for STMT in FN and store it
247 : : in MAP, return the total count for all inlined indirect calls. */
248 : : gcov_type find_icall_target_map (tree fn, gcall *stmt,
249 : : icall_target_map *map) const;
250 : :
251 : : /* Remove inlined indirect call target profile for STMT in FN. */
252 : : void remove_icall_target (tree fn, gcall *stmt);
253 : :
254 : : /* Mark LOC as annotated. */
255 : : void mark_annotated (location_t loc);
256 : :
257 : : private:
258 : : /* Callsite, represented as (decl_lineno, callee_function_name_index). */
259 : : typedef std::pair<unsigned, unsigned> callsite;
260 : :
261 : : /* Map from callsite to callee function_instance. */
262 : : typedef std::map<callsite, function_instance *> callsite_map;
263 : :
264 : 0 : function_instance (unsigned name, gcov_type head_count)
265 : 0 : : name_ (name), total_count_ (0), head_count_ (head_count)
266 : : {
267 : : }
268 : :
269 : : /* Map from source location (decl_lineno) to profile (count_info). */
270 : : typedef std::map<unsigned, count_info> position_count_map;
271 : :
272 : : /* function_instance name index in the string_table. */
273 : : unsigned name_;
274 : :
275 : : /* Total sample count. */
276 : : gcov_type total_count_;
277 : :
278 : : /* Entry BB's sample count. */
279 : : gcov_type head_count_;
280 : :
281 : : /* Map from callsite location to callee function_instance. */
282 : : callsite_map callsites;
283 : :
284 : : /* Map from source location to count_info. */
285 : : position_count_map pos_counts;
286 : : };
287 : :
288 : : /* Profile for all functions. */
289 : : class autofdo_source_profile
290 : : {
291 : : public:
292 : : static autofdo_source_profile *
293 : 0 : create ()
294 : : {
295 : 0 : autofdo_source_profile *map = new autofdo_source_profile ();
296 : :
297 : 0 : if (map->read ())
298 : : return map;
299 : 0 : delete map;
300 : 0 : return NULL;
301 : : }
302 : :
303 : : ~autofdo_source_profile ();
304 : :
305 : : /* For a given DECL, returns the top-level function_instance. */
306 : : function_instance *get_function_instance_by_decl (tree decl) const;
307 : :
308 : : /* Find count_info for a given gimple STMT. If found, store the count_info
309 : : in INFO and return true; otherwise return false.
310 : : NODE can be used to specify particular inline clone. */
311 : : bool get_count_info (gimple *stmt, count_info *info,
312 : : cgraph_node *node = NULL) const;
313 : :
314 : : /* Find count_info for a given gimple location GIMPLE_LOC. If found,
315 : : store the count_info in INFO and return true; otherwise return false.
316 : : NODE can be used to specify particular inline clone. */
317 : : bool get_count_info (location_t gimple_loc, count_info *info,
318 : : cgraph_node *node = NULL) const;
319 : :
320 : : /* Find total count of the callee of EDGE. */
321 : : gcov_type get_callsite_total_count (struct cgraph_edge *edge) const;
322 : :
323 : : /* Update value profile INFO for STMT within NODE from the inlined indirect
324 : : callsite. Return true if INFO is updated. */
325 : : bool update_inlined_ind_target (gcall *stmt, count_info *info,
326 : : cgraph_node *node);
327 : :
328 : : void remove_icall_target (cgraph_edge *e);
329 : : private:
330 : : /* Map from function_instance name index (in string_table) to
331 : : function_instance. */
332 : : typedef std::map<unsigned, function_instance *> name_function_instance_map;
333 : :
334 : 0 : autofdo_source_profile () {}
335 : :
336 : : /* Read AutoFDO profile and returns TRUE on success. */
337 : : bool read ();
338 : :
339 : : /* Return the function_instance in the profile that correspond to the
340 : : inline STACK. */
341 : : function_instance *
342 : : get_function_instance_by_inline_stack (const inline_stack &stack) const;
343 : :
344 : : name_function_instance_map map_;
345 : : };
346 : :
347 : : /* Store the strings read from the profile data file. */
348 : : static string_table *afdo_string_table;
349 : :
350 : : /* Store the AutoFDO source profile. */
351 : : static autofdo_source_profile *afdo_source_profile;
352 : :
353 : : /* gcov_summary structure to store the profile_info. */
354 : : static gcov_summary *afdo_profile_info;
355 : :
356 : : /* Helper functions. */
357 : :
358 : : /* Return the original name of NAME: strip the suffix that starts
359 : : with '.' Caller is responsible for freeing RET. */
360 : :
361 : : static char *
362 : 0 : get_original_name (const char *name)
363 : : {
364 : 0 : char *ret = xstrdup (name);
365 : 0 : char *find = strchr (ret, '.');
366 : 0 : if (find != NULL)
367 : 0 : *find = 0;
368 : 0 : return ret;
369 : : }
370 : :
371 : : /* Return the combined location, which is a 32bit integer in which
372 : : higher 16 bits stores the line offset of LOC to the start lineno
373 : : of DECL, The lower 16 bits stores the discriminator. */
374 : :
375 : : static unsigned
376 : 0 : get_combined_location (location_t loc, tree decl)
377 : : {
378 : : /* TODO: allow more bits for line and less bits for discriminator. */
379 : 0 : if (LOCATION_LINE (loc) - DECL_SOURCE_LINE (decl) >= (1<<16))
380 : 0 : warning_at (loc, OPT_Woverflow, "offset exceeds 16 bytes");
381 : 0 : return ((LOCATION_LINE (loc) - DECL_SOURCE_LINE (decl)) << 16)
382 : 0 : | get_discriminator_from_loc (loc);
383 : : }
384 : :
385 : : /* Return the function decl of a given lexical BLOCK. */
386 : :
387 : : static tree
388 : 0 : get_function_decl_from_block (tree block)
389 : : {
390 : 0 : if (!inlined_function_outer_scope_p (block))
391 : : return NULL_TREE;
392 : :
393 : 0 : return BLOCK_ABSTRACT_ORIGIN (block);
394 : : }
395 : :
396 : : /* Dump STACK to F. */
397 : :
398 : : static void
399 : 0 : dump_inline_stack (FILE *f, inline_stack *stack)
400 : : {
401 : 0 : bool first = true;
402 : 0 : for (decl_lineno &p : *stack)
403 : : {
404 : 0 : fprintf(f, "%s%s:%i.%i",
405 : : first ? "" : "; ",
406 : 0 : IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (p.first)),
407 : : p.second >> 16,
408 : 0 : p.second & 65535);
409 : 0 : first = false;
410 : : }
411 : 0 : fprintf (f, "\n");
412 : 0 : }
413 : :
414 : : /* Store inline stack for STMT in STACK. */
415 : :
416 : : static void
417 : 0 : get_inline_stack (location_t locus, inline_stack *stack,
418 : : tree fn = current_function_decl)
419 : : {
420 : 0 : if (LOCATION_LOCUS (locus) == UNKNOWN_LOCATION)
421 : : return;
422 : :
423 : 0 : tree block = LOCATION_BLOCK (locus);
424 : 0 : if (block && TREE_CODE (block) == BLOCK)
425 : : {
426 : 0 : for (block = BLOCK_SUPERCONTEXT (block);
427 : 0 : block && (TREE_CODE (block) == BLOCK);
428 : 0 : block = BLOCK_SUPERCONTEXT (block))
429 : : {
430 : 0 : location_t tmp_locus = BLOCK_SOURCE_LOCATION (block);
431 : 0 : if (LOCATION_LOCUS (tmp_locus) == UNKNOWN_LOCATION)
432 : 0 : continue;
433 : :
434 : 0 : tree decl = get_function_decl_from_block (block);
435 : 0 : stack->safe_push (
436 : 0 : std::make_pair (decl, get_combined_location (locus, decl)));
437 : 0 : locus = tmp_locus;
438 : : }
439 : : }
440 : 0 : stack->safe_push (std::make_pair (fn, get_combined_location (locus, fn)));
441 : : }
442 : :
443 : : /* Same as get_inline_stack for a given node which may be
444 : : an inline clone. If NODE is NULL, assume current_function_decl. */
445 : : static void
446 : 0 : get_inline_stack_in_node (location_t locus, inline_stack *stack,
447 : : cgraph_node *node)
448 : : {
449 : 0 : if (!node)
450 : 0 : return get_inline_stack (locus, stack);
451 : 0 : do
452 : : {
453 : 0 : get_inline_stack (locus, stack, node->decl);
454 : : /* If caller is inlined, continue building stack. */
455 : 0 : if (!node->inlined_to)
456 : : node = NULL;
457 : : else
458 : : {
459 : 0 : locus = gimple_location (node->callers->call_stmt);
460 : 0 : node = node->callers->caller;
461 : : }
462 : : }
463 : 0 : while (node);
464 : : }
465 : :
466 : : /* Return STMT's combined location, which is a 32bit integer in which
467 : : higher 16 bits stores the line offset of LOC to the start lineno
468 : : of DECL, The lower 16 bits stores the discriminator. */
469 : :
470 : : static unsigned
471 : 0 : get_relative_location_for_stmt (tree fn, gimple *stmt)
472 : : {
473 : 0 : location_t locus = gimple_location (stmt);
474 : 0 : if (LOCATION_LOCUS (locus) == UNKNOWN_LOCATION)
475 : : return UNKNOWN_LOCATION;
476 : :
477 : 0 : for (tree block = gimple_block (stmt); block && (TREE_CODE (block) == BLOCK);
478 : 0 : block = BLOCK_SUPERCONTEXT (block))
479 : 0 : if (LOCATION_LOCUS (BLOCK_SOURCE_LOCATION (block)) != UNKNOWN_LOCATION)
480 : 0 : return get_combined_location (locus,
481 : 0 : get_function_decl_from_block (block));
482 : 0 : return get_combined_location (locus, fn);
483 : : }
484 : :
485 : : /* Member functions for string_table. */
486 : :
487 : : /* Deconstructor. */
488 : :
489 : 0 : string_table::~string_table ()
490 : : {
491 : 0 : for (unsigned i = 0; i < vector_.length (); i++)
492 : 0 : free (vector_[i]);
493 : 0 : }
494 : :
495 : :
496 : : /* Return the index of a given function NAME. Return -1 if NAME is not
497 : : found in string table. */
498 : :
499 : : int
500 : 0 : string_table::get_index (const char *name) const
501 : : {
502 : 0 : if (name == NULL)
503 : : return -1;
504 : 0 : string_index_map::const_iterator iter = map_.find (name);
505 : 0 : if (iter == map_.end ())
506 : : return -1;
507 : :
508 : 0 : return iter->second;
509 : : }
510 : :
511 : : /* Return the index of a given function DECL. Return -1 if DECL is not
512 : : found in string table. */
513 : :
514 : : int
515 : 0 : string_table::get_index_by_decl (tree decl) const
516 : : {
517 : 0 : char *name
518 : 0 : = get_original_name (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
519 : 0 : int ret = get_index (name);
520 : 0 : free (name);
521 : 0 : if (ret != -1)
522 : : return ret;
523 : 0 : ret = get_index (lang_hooks.dwarf_name (decl, 0));
524 : 0 : if (ret != -1)
525 : : return ret;
526 : 0 : if (DECL_FROM_INLINE (decl))
527 : 0 : return get_index_by_decl (DECL_ABSTRACT_ORIGIN (decl));
528 : :
529 : : return -1;
530 : : }
531 : :
532 : : /* Return the function name of a given INDEX. */
533 : :
534 : : const char *
535 : 0 : string_table::get_name (int index) const
536 : : {
537 : 0 : gcc_assert (index > 0 && index < (int)vector_.length ());
538 : 0 : return vector_[index];
539 : : }
540 : :
541 : : /* Read the string table. Return TRUE if reading is successful. */
542 : :
543 : : bool
544 : 0 : string_table::read ()
545 : : {
546 : 0 : if (gcov_read_unsigned () != GCOV_TAG_AFDO_FILE_NAMES)
547 : : return false;
548 : : /* Skip the length of the section. */
549 : 0 : gcov_read_unsigned ();
550 : : /* Read in the file name table. */
551 : 0 : unsigned string_num = gcov_read_unsigned ();
552 : 0 : for (unsigned i = 0; i < string_num; i++)
553 : : {
554 : 0 : vector_.safe_push (get_original_name (gcov_read_string ()));
555 : 0 : map_[vector_.last ()] = i;
556 : : }
557 : : return true;
558 : : }
559 : :
560 : : /* Member functions for function_instance. */
561 : :
562 : 0 : function_instance::~function_instance ()
563 : : {
564 : 0 : for (callsite_map::iterator iter = callsites.begin ();
565 : 0 : iter != callsites.end (); ++iter)
566 : 0 : delete iter->second;
567 : 0 : }
568 : :
569 : : /* Traverse callsites of the current function_instance to find one at the
570 : : location of LINENO and callee name represented in DECL. */
571 : :
572 : : function_instance *
573 : 0 : function_instance::get_function_instance_by_decl (unsigned lineno,
574 : : tree decl) const
575 : : {
576 : 0 : int func_name_idx = afdo_string_table->get_index_by_decl (decl);
577 : 0 : if (func_name_idx != -1)
578 : : {
579 : 0 : callsite_map::const_iterator ret
580 : 0 : = callsites.find (std::make_pair (lineno, func_name_idx));
581 : 0 : if (ret != callsites.end ())
582 : 0 : return ret->second;
583 : : }
584 : 0 : func_name_idx
585 : 0 : = afdo_string_table->get_index (lang_hooks.dwarf_name (decl, 0));
586 : 0 : if (func_name_idx != -1)
587 : : {
588 : 0 : callsite_map::const_iterator ret
589 : 0 : = callsites.find (std::make_pair (lineno, func_name_idx));
590 : 0 : if (ret != callsites.end ())
591 : 0 : return ret->second;
592 : : }
593 : 0 : if (DECL_FROM_INLINE (decl))
594 : 0 : return get_function_instance_by_decl (lineno, DECL_ABSTRACT_ORIGIN (decl));
595 : :
596 : : return NULL;
597 : : }
598 : :
599 : : /* Merge profile of clones. Note that cloning hasnt been performed when
600 : : we annotate the CFG (at this stage). */
601 : :
602 : 0 : void function_instance::merge (function_instance *other)
603 : : {
604 : 0 : total_count_ += other->total_count_;
605 : 0 : head_count_ += other->head_count_;
606 : :
607 : 0 : for (callsite_map::const_iterator iter = other->callsites.begin ();
608 : 0 : iter != other->callsites.end (); ++iter)
609 : 0 : if (callsites.count (iter->first) == 0)
610 : 0 : callsites[iter->first] = iter->second;
611 : :
612 : 0 : for (position_count_map::const_iterator iter = other->pos_counts.begin ();
613 : 0 : iter != other->pos_counts.end (); ++iter)
614 : 0 : if (pos_counts.count (iter->first) == 0)
615 : 0 : pos_counts[iter->first] = iter->second;
616 : : else
617 : 0 : pos_counts[iter->first].count += iter->second.count;
618 : 0 : }
619 : :
620 : : /* Return profile info for LOC in INFO. */
621 : :
622 : : bool
623 : 0 : function_instance::get_count_info (location_t loc, count_info *info) const
624 : : {
625 : 0 : position_count_map::const_iterator iter = pos_counts.find (loc);
626 : 0 : if (iter == pos_counts.end ())
627 : : return false;
628 : 0 : *info = iter->second;
629 : 0 : return true;
630 : : }
631 : :
632 : : /* Read the inlined indirect call target profile for STMT and store it in
633 : : MAP, return the total count for all inlined indirect calls. */
634 : :
635 : : gcov_type
636 : 0 : function_instance::find_icall_target_map (tree fn, gcall *stmt,
637 : : icall_target_map *map) const
638 : : {
639 : 0 : gcov_type ret = 0;
640 : 0 : unsigned stmt_offset = get_relative_location_for_stmt (fn, stmt);
641 : :
642 : 0 : for (callsite_map::const_iterator iter = callsites.begin ();
643 : 0 : iter != callsites.end (); ++iter)
644 : : {
645 : 0 : unsigned callee = iter->second->name ();
646 : : /* Check if callsite location match the stmt. */
647 : 0 : if (iter->first.first != stmt_offset)
648 : 0 : continue;
649 : 0 : struct cgraph_node *node = cgraph_node::get_for_asmname (
650 : : get_identifier (afdo_string_table->get_name (callee)));
651 : 0 : if (node == NULL)
652 : 0 : continue;
653 : 0 : (*map)[callee] = iter->second->total_count ();
654 : 0 : ret += iter->second->total_count ();
655 : : }
656 : 0 : return ret;
657 : : }
658 : :
659 : : /* Remove the inlined indirect call target profile for STMT. */
660 : :
661 : : void
662 : 0 : function_instance::remove_icall_target (tree fn, gcall *stmt)
663 : : {
664 : 0 : unsigned stmt_offset = get_relative_location_for_stmt (fn, stmt);
665 : 0 : int n = 0;
666 : :
667 : 0 : for (callsite_map::const_iterator iter = callsites.begin ();
668 : 0 : iter != callsites.end ();)
669 : 0 : if (iter->first.first != stmt_offset)
670 : 0 : ++iter;
671 : : else
672 : : {
673 : 0 : iter = callsites.erase (iter);
674 : 0 : n++;
675 : : }
676 : : /* TODO: If we add support for multiple targets, we may want to
677 : : remove only those we succesfully inlined. */
678 : 0 : gcc_assert (n);
679 : 0 : }
680 : :
681 : : /* Read the profile and create a function_instance with head count as
682 : : HEAD_COUNT. Recursively read callsites to create nested function_instances
683 : : too. STACK is used to track the recursive creation process. */
684 : :
685 : : /* function instance profile format:
686 : :
687 : : ENTRY_COUNT: 8 bytes
688 : : NAME_INDEX: 4 bytes
689 : : NUM_POS_COUNTS: 4 bytes
690 : : NUM_CALLSITES: 4 byte
691 : : POS_COUNT_1:
692 : : POS_1_OFFSET: 4 bytes
693 : : NUM_TARGETS: 4 bytes
694 : : COUNT: 8 bytes
695 : : TARGET_1:
696 : : VALUE_PROFILE_TYPE: 4 bytes
697 : : TARGET_IDX: 8 bytes
698 : : COUNT: 8 bytes
699 : : TARGET_2
700 : : ...
701 : : TARGET_n
702 : : POS_COUNT_2
703 : : ...
704 : : POS_COUNT_N
705 : : CALLSITE_1:
706 : : CALLSITE_1_OFFSET: 4 bytes
707 : : FUNCTION_INSTANCE_PROFILE (nested)
708 : : CALLSITE_2
709 : : ...
710 : : CALLSITE_n. */
711 : :
712 : : function_instance *
713 : 0 : function_instance::read_function_instance (function_instance_stack *stack,
714 : : gcov_type head_count)
715 : : {
716 : 0 : unsigned name = gcov_read_unsigned ();
717 : 0 : unsigned num_pos_counts = gcov_read_unsigned ();
718 : 0 : unsigned num_callsites = gcov_read_unsigned ();
719 : 0 : function_instance *s = new function_instance (name, head_count);
720 : 0 : stack->safe_push (s);
721 : :
722 : 0 : for (unsigned i = 0; i < num_pos_counts; i++)
723 : : {
724 : 0 : unsigned offset = gcov_read_unsigned ();
725 : 0 : unsigned num_targets = gcov_read_unsigned ();
726 : 0 : gcov_type count = gcov_read_counter ();
727 : 0 : s->pos_counts[offset].count = count;
728 : 0 : afdo_profile_info->sum_max = std::max (afdo_profile_info->sum_max,
729 : : count);
730 : :
731 : 0 : for (unsigned j = 0; j < stack->length (); j++)
732 : 0 : (*stack)[j]->total_count_ += count;
733 : 0 : for (unsigned j = 0; j < num_targets; j++)
734 : : {
735 : : /* Only indirect call target histogram is supported now. */
736 : 0 : gcov_read_unsigned ();
737 : 0 : gcov_type target_idx = gcov_read_counter ();
738 : 0 : s->pos_counts[offset].targets[target_idx] = gcov_read_counter ();
739 : : }
740 : : }
741 : 0 : for (unsigned i = 0; i < num_callsites; i++)
742 : : {
743 : 0 : unsigned offset = gcov_read_unsigned ();
744 : 0 : function_instance *callee_function_instance
745 : 0 : = read_function_instance (stack, 0);
746 : 0 : s->callsites[std::make_pair (offset, callee_function_instance->name ())]
747 : 0 : = callee_function_instance;
748 : : }
749 : 0 : stack->pop ();
750 : 0 : return s;
751 : : }
752 : :
753 : : /* Member functions for autofdo_source_profile. */
754 : :
755 : 0 : autofdo_source_profile::~autofdo_source_profile ()
756 : : {
757 : 0 : for (name_function_instance_map::const_iterator iter = map_.begin ();
758 : 0 : iter != map_.end (); ++iter)
759 : 0 : delete iter->second;
760 : 0 : }
761 : :
762 : : /* For a given DECL, returns the top-level function_instance. */
763 : :
764 : : function_instance *
765 : 0 : autofdo_source_profile::get_function_instance_by_decl (tree decl) const
766 : : {
767 : 0 : int index = afdo_string_table->get_index_by_decl (decl);
768 : 0 : if (index == -1)
769 : : return NULL;
770 : 0 : name_function_instance_map::const_iterator ret = map_.find (index);
771 : 0 : return ret == map_.end () ? NULL : ret->second;
772 : : }
773 : :
774 : : /* Find count_info for a given gimple STMT. If found, store the count_info
775 : : in INFO and return true; otherwise return false. */
776 : :
777 : : bool
778 : 0 : autofdo_source_profile::get_count_info (gimple *stmt, count_info *info,
779 : : cgraph_node *node) const
780 : : {
781 : 0 : return get_count_info (gimple_location (stmt), info, node);
782 : : }
783 : :
784 : : bool
785 : 0 : autofdo_source_profile::get_count_info (location_t gimple_loc,
786 : : count_info *info,
787 : : cgraph_node *node) const
788 : : {
789 : 0 : if (LOCATION_LOCUS (gimple_loc) == cfun->function_end_locus)
790 : : return false;
791 : :
792 : 0 : inline_stack stack;
793 : 0 : get_inline_stack_in_node (gimple_loc, &stack, node);
794 : 0 : if (stack.length () == 0)
795 : : return false;
796 : 0 : function_instance *s = get_function_instance_by_inline_stack (stack);
797 : 0 : if (s == NULL)
798 : : return false;
799 : 0 : return s->get_count_info (stack[0].second, info);
800 : 0 : }
801 : :
802 : : /* Update value profile INFO for STMT from the inlined indirect callsite.
803 : : Return true if INFO is updated. */
804 : :
805 : : bool
806 : 0 : autofdo_source_profile::update_inlined_ind_target (gcall *stmt,
807 : : count_info *info,
808 : : cgraph_node *node)
809 : : {
810 : 0 : if (dump_file)
811 : : {
812 : 0 : fprintf (dump_file, "Checking indirect call -> direct call ");
813 : 0 : print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
814 : : }
815 : :
816 : 0 : if (LOCATION_LOCUS (gimple_location (stmt)) == cfun->function_end_locus)
817 : : {
818 : 0 : if (dump_file)
819 : 0 : fprintf (dump_file, " bad locus (funciton end)\n");
820 : 0 : return false;
821 : : }
822 : :
823 : 0 : count_info old_info;
824 : 0 : get_count_info (stmt, &old_info, node);
825 : 0 : gcov_type total = 0;
826 : 0 : for (icall_target_map::const_iterator iter = old_info.targets.begin ();
827 : 0 : iter != old_info.targets.end (); ++iter)
828 : 0 : total += iter->second;
829 : :
830 : : /* Program behavior changed, original promoted (and inlined) target is not
831 : : hot any more. Will avoid promote the original target.
832 : :
833 : : To check if original promoted target is still hot, we check the total
834 : : count of the unpromoted targets (stored in TOTAL). If a callsite count
835 : : (stored in INFO) is smaller than half of the total count, the original
836 : : promoted target is considered not hot any more. */
837 : 0 : if (info->count < total / 2)
838 : : {
839 : 0 : if (dump_file)
840 : 0 : fprintf (dump_file, " not hot anymore %ld < %ld",
841 : : (long)info->count,
842 : : (long)total /2);
843 : 0 : return false;
844 : : }
845 : :
846 : 0 : inline_stack stack;
847 : 0 : get_inline_stack_in_node (gimple_location (stmt), &stack, node);
848 : 0 : if (stack.length () == 0)
849 : : {
850 : 0 : if (dump_file)
851 : 0 : fprintf (dump_file, " no inline stack\n");
852 : 0 : return false;
853 : : }
854 : 0 : function_instance *s = get_function_instance_by_inline_stack (stack);
855 : 0 : if (s == NULL)
856 : : {
857 : 0 : if (dump_file)
858 : : {
859 : 0 : fprintf (dump_file, " function not found in inline stack:");
860 : 0 : dump_inline_stack (dump_file, &stack);
861 : : }
862 : 0 : return false;
863 : : }
864 : 0 : icall_target_map map;
865 : 0 : if (s->find_icall_target_map (node ? node->decl
866 : : : current_function_decl,
867 : : stmt, &map) == 0)
868 : : {
869 : 0 : if (dump_file)
870 : : {
871 : 0 : fprintf (dump_file, " no target map for stack: ");
872 : 0 : dump_inline_stack (dump_file, &stack);
873 : : }
874 : 0 : return false;
875 : : }
876 : 0 : for (icall_target_map::const_iterator iter = map.begin ();
877 : 0 : iter != map.end (); ++iter)
878 : 0 : info->targets[iter->first] = iter->second;
879 : 0 : if (dump_file)
880 : : {
881 : 0 : fprintf (dump_file, " looks good; stack:");
882 : 0 : dump_inline_stack (dump_file, &stack);
883 : : }
884 : : return true;
885 : 0 : }
886 : :
887 : : void
888 : 0 : autofdo_source_profile::remove_icall_target (cgraph_edge *e)
889 : : {
890 : 0 : autofdo::inline_stack stack;
891 : 0 : autofdo::get_inline_stack_in_node (gimple_location (e->call_stmt),
892 : : &stack, e->caller);
893 : 0 : autofdo::function_instance *s
894 : 0 : = get_function_instance_by_inline_stack (stack);
895 : 0 : s->remove_icall_target (e->caller->decl, e->call_stmt);
896 : 0 : }
897 : :
898 : : /* Find total count of the callee of EDGE. */
899 : :
900 : : gcov_type
901 : 0 : autofdo_source_profile::get_callsite_total_count (
902 : : struct cgraph_edge *edge) const
903 : : {
904 : 0 : inline_stack stack;
905 : 0 : stack.safe_push (std::make_pair (edge->callee->decl, 0));
906 : :
907 : 0 : get_inline_stack_in_node (gimple_location (edge->call_stmt), &stack,
908 : : edge->caller);
909 : :
910 : 0 : function_instance *s = get_function_instance_by_inline_stack (stack);
911 : 0 : if (s == NULL
912 : 0 : ||(afdo_string_table->get_index_by_decl (edge->callee->decl)
913 : 0 : != s->name()))
914 : 0 : return 0;
915 : :
916 : 0 : return s->total_count ();
917 : 0 : }
918 : :
919 : : /* Read AutoFDO profile and returns TRUE on success. */
920 : :
921 : : /* source profile format:
922 : :
923 : : GCOV_TAG_AFDO_FUNCTION: 4 bytes
924 : : LENGTH: 4 bytes
925 : : NUM_FUNCTIONS: 4 bytes
926 : : FUNCTION_INSTANCE_1
927 : : FUNCTION_INSTANCE_2
928 : : ...
929 : : FUNCTION_INSTANCE_N. */
930 : :
931 : : bool
932 : 0 : autofdo_source_profile::read ()
933 : : {
934 : 0 : if (gcov_read_unsigned () != GCOV_TAG_AFDO_FUNCTION)
935 : : {
936 : 0 : inform (UNKNOWN_LOCATION, "Not expected TAG.");
937 : 0 : return false;
938 : : }
939 : :
940 : : /* Skip the length of the section. */
941 : 0 : gcov_read_unsigned ();
942 : :
943 : : /* Read in the function/callsite profile, and store it in local
944 : : data structure. */
945 : 0 : unsigned function_num = gcov_read_unsigned ();
946 : 0 : int profile_pass_num
947 : 0 : = g->get_passes ()->get_pass_auto_profile ()->static_pass_number;
948 : 0 : g->get_dumps ()->dump_start (profile_pass_num, NULL);
949 : 0 : for (unsigned i = 0; i < function_num; i++)
950 : : {
951 : 0 : function_instance::function_instance_stack stack;
952 : 0 : function_instance *s = function_instance::read_function_instance (
953 : : &stack, gcov_read_counter ());
954 : 0 : int fun_id = afdo_string_table->get_index
955 : 0 : (afdo_string_table->get_name (s->name ()));
956 : : /* If function_instace with get_original_name (without the clone
957 : : suffix) exixts, merge the function instances. */
958 : 0 : if (map_.count (fun_id) == 0)
959 : 0 : map_[fun_id] = s;
960 : : else
961 : : {
962 : : /* Since this is invoked very early, before the pass
963 : : manager, we need to set up the dumping explicitly. This is
964 : : similar to the handling in finish_optimization_passes. */
965 : 0 : if (dump_enabled_p ())
966 : : {
967 : 0 : dump_user_location_t loc
968 : 0 : = dump_user_location_t::from_location_t (input_location);
969 : 0 : dump_printf_loc (MSG_NOTE, loc, "Merging profile for %s\n",
970 : : afdo_string_table->get_name (s->name ()));
971 : : }
972 : 0 : map_[fun_id]->merge (s);
973 : : }
974 : 0 : }
975 : 0 : g->get_dumps ()->dump_finish (profile_pass_num);
976 : 0 : return true;
977 : : }
978 : :
979 : : /* Return the function_instance in the profile that correspond to the
980 : : inline STACK. */
981 : :
982 : : function_instance *
983 : 0 : autofdo_source_profile::get_function_instance_by_inline_stack (
984 : : const inline_stack &stack) const
985 : : {
986 : 0 : name_function_instance_map::const_iterator iter = map_.find (
987 : 0 : afdo_string_table->get_index_by_decl (stack[stack.length () - 1].first));
988 : 0 : if (iter == map_.end())
989 : : return NULL;
990 : 0 : function_instance *s = iter->second;
991 : 0 : for (unsigned i = stack.length() - 1; i > 0; i--)
992 : : {
993 : 0 : s = s->get_function_instance_by_decl (
994 : 0 : stack[i].second, stack[i - 1].first);
995 : 0 : if (s == NULL)
996 : : return NULL;
997 : : }
998 : : return s;
999 : : }
1000 : :
1001 : : /* Module profile is only used by LIPO. Here we simply ignore it. */
1002 : :
1003 : : static void
1004 : 0 : fake_read_autofdo_module_profile ()
1005 : : {
1006 : : /* Read in the module info. */
1007 : 0 : gcov_read_unsigned ();
1008 : :
1009 : : /* Skip the length of the section. */
1010 : 0 : gcov_read_unsigned ();
1011 : :
1012 : : /* Read in the file name table. */
1013 : 0 : unsigned total_module_num = gcov_read_unsigned ();
1014 : 0 : gcc_assert (total_module_num == 0);
1015 : 0 : }
1016 : :
1017 : : /* Read data from profile data file. */
1018 : :
1019 : : static void
1020 : 0 : read_profile (void)
1021 : : {
1022 : 0 : if (gcov_open (auto_profile_file, 1) == 0)
1023 : : {
1024 : 0 : error ("cannot open profile file %s", auto_profile_file);
1025 : 0 : return;
1026 : : }
1027 : :
1028 : 0 : if (gcov_read_unsigned () != GCOV_DATA_MAGIC)
1029 : : {
1030 : 0 : error ("AutoFDO profile magic number does not match");
1031 : 0 : return;
1032 : : }
1033 : :
1034 : : /* Skip the version number. */
1035 : 0 : unsigned version = gcov_read_unsigned ();
1036 : 0 : if (version != AUTO_PROFILE_VERSION)
1037 : : {
1038 : 0 : error ("AutoFDO profile version %u does not match %u",
1039 : : version, AUTO_PROFILE_VERSION);
1040 : 0 : return;
1041 : : }
1042 : :
1043 : : /* Skip the empty integer. */
1044 : 0 : gcov_read_unsigned ();
1045 : :
1046 : : /* string_table. */
1047 : 0 : afdo_string_table = new string_table ();
1048 : 0 : if (!afdo_string_table->read())
1049 : : {
1050 : 0 : error ("cannot read string table from %s", auto_profile_file);
1051 : 0 : return;
1052 : : }
1053 : :
1054 : : /* autofdo_source_profile. */
1055 : 0 : afdo_source_profile = autofdo_source_profile::create ();
1056 : 0 : if (afdo_source_profile == NULL)
1057 : : {
1058 : 0 : error ("cannot read function profile from %s", auto_profile_file);
1059 : 0 : return;
1060 : : }
1061 : :
1062 : : /* autofdo_module_profile. */
1063 : 0 : fake_read_autofdo_module_profile ();
1064 : : }
1065 : :
1066 : : /* From AutoFDO profiles, find values inside STMT for that we want to measure
1067 : : histograms for indirect-call optimization.
1068 : :
1069 : : This function is actually served for 2 purposes:
1070 : : * before annotation, we need to mark histogram, promote and inline
1071 : : * after annotation, we just need to mark, and let follow-up logic to
1072 : : decide if it needs to promote and inline. */
1073 : :
1074 : : static bool
1075 : 0 : afdo_indirect_call (gcall *stmt, const icall_target_map &map,
1076 : : bool transform, cgraph_edge *indirect_edge)
1077 : : {
1078 : 0 : tree callee;
1079 : :
1080 : 0 : if (map.size () == 0)
1081 : : {
1082 : 0 : if (dump_file)
1083 : 0 : fprintf (dump_file, "No targets found\n");
1084 : 0 : return false;
1085 : : }
1086 : 0 : if (!stmt)
1087 : : {
1088 : 0 : if (dump_file)
1089 : 0 : fprintf (dump_file, "No call statement\n");
1090 : 0 : return false;
1091 : : }
1092 : 0 : if (gimple_call_internal_p (stmt))
1093 : : {
1094 : 0 : if (dump_file)
1095 : 0 : fprintf (dump_file, "Internal call\n");
1096 : 0 : return false;
1097 : : }
1098 : 0 : if (gimple_call_fndecl (stmt) != NULL_TREE)
1099 : : {
1100 : 0 : if (dump_file)
1101 : 0 : fprintf (dump_file, "Call is already direct\n");
1102 : 0 : return false;
1103 : : }
1104 : :
1105 : 0 : gcov_type total = 0;
1106 : 0 : icall_target_map::const_iterator max_iter = map.end ();
1107 : :
1108 : 0 : for (icall_target_map::const_iterator iter = map.begin ();
1109 : 0 : iter != map.end (); ++iter)
1110 : : {
1111 : 0 : total += iter->second;
1112 : 0 : if (max_iter == map.end () || max_iter->second < iter->second)
1113 : : max_iter = iter;
1114 : : }
1115 : 0 : struct cgraph_node *direct_call = cgraph_node::get_for_asmname (
1116 : 0 : get_identifier (afdo_string_table->get_name (max_iter->first)));
1117 : 0 : if (direct_call == NULL)
1118 : : {
1119 : 0 : if (dump_file)
1120 : 0 : fprintf (dump_file, "Failed to find cgraph node for %s\n",
1121 : 0 : afdo_string_table->get_name (max_iter->first));
1122 : 0 : return false;
1123 : : }
1124 : :
1125 : 0 : callee = gimple_call_fn (stmt);
1126 : :
1127 : 0 : if (!transform)
1128 : : {
1129 : 0 : if (!direct_call->profile_id)
1130 : : {
1131 : 0 : if (dump_file)
1132 : 0 : fprintf (dump_file, "No profile id\n");
1133 : 0 : return false;
1134 : : }
1135 : 0 : histogram_value hist = gimple_alloc_histogram_value (
1136 : : cfun, HIST_TYPE_INDIR_CALL, stmt, callee);
1137 : 0 : hist->n_counters = 4;
1138 : 0 : hist->hvalue.counters = XNEWVEC (gcov_type, hist->n_counters);
1139 : 0 : gimple_add_histogram_value (cfun, stmt, hist);
1140 : :
1141 : : /* Total counter */
1142 : 0 : hist->hvalue.counters[0] = total;
1143 : : /* Number of value/counter pairs */
1144 : 0 : hist->hvalue.counters[1] = 1;
1145 : : /* Value */
1146 : 0 : hist->hvalue.counters[2] = direct_call->profile_id;
1147 : : /* Counter */
1148 : 0 : hist->hvalue.counters[3] = max_iter->second;
1149 : :
1150 : 0 : if (!direct_call->profile_id)
1151 : : {
1152 : 0 : if (dump_file)
1153 : 0 : fprintf (dump_file, "Histogram attached\n");
1154 : 0 : return false;
1155 : : }
1156 : : return false;
1157 : : }
1158 : :
1159 : 0 : if (dump_file)
1160 : : {
1161 : 0 : fprintf (dump_file, "Indirect call -> direct call ");
1162 : 0 : print_generic_expr (dump_file, callee, TDF_SLIM);
1163 : 0 : fprintf (dump_file, " => ");
1164 : 0 : print_generic_expr (dump_file, direct_call->decl, TDF_SLIM);
1165 : : }
1166 : :
1167 : 0 : if (!direct_call->definition)
1168 : : {
1169 : 0 : if (dump_file)
1170 : 0 : fprintf (dump_file, " no definition available\n");
1171 : 0 : return false;
1172 : : }
1173 : :
1174 : 0 : if (dump_file)
1175 : : {
1176 : 0 : fprintf (dump_file, " transformation on insn ");
1177 : 0 : print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1178 : 0 : fprintf (dump_file, "\n");
1179 : : }
1180 : :
1181 : 0 : indirect_edge->make_speculative
1182 : 0 : (direct_call,
1183 : 0 : gimple_bb (stmt)->count.apply_scale (99, 100));
1184 : 0 : return true;
1185 : : }
1186 : :
1187 : : /* From AutoFDO profiles, find values inside STMT for that we want to measure
1188 : : histograms and adds them to list VALUES. */
1189 : :
1190 : : static bool
1191 : 0 : afdo_vpt (gcall *gs, const icall_target_map &map,
1192 : : bool transform, cgraph_edge *indirect_edge)
1193 : : {
1194 : 0 : return afdo_indirect_call (gs, map, transform, indirect_edge);
1195 : : }
1196 : :
1197 : : typedef std::set<basic_block> bb_set;
1198 : :
1199 : : static bool
1200 : 0 : is_bb_annotated (const basic_block bb, const bb_set &annotated)
1201 : : {
1202 : 0 : if (annotated.find (bb) != annotated.end ())
1203 : : {
1204 : 0 : gcc_checking_assert (bb->count.quality () == AFDO
1205 : : || !bb->count.nonzero_p ());
1206 : : return true;
1207 : : }
1208 : 0 : gcc_checking_assert (bb->count.quality () != AFDO
1209 : : || !bb->count.nonzero_p ());
1210 : : return false;
1211 : : }
1212 : :
1213 : : static void
1214 : 0 : set_bb_annotated (basic_block bb, bb_set *annotated)
1215 : : {
1216 : 0 : gcc_checking_assert (bb->count.quality () == AFDO
1217 : : || !bb->count.nonzero_p ());
1218 : 0 : annotated->insert (bb);
1219 : 0 : }
1220 : :
1221 : : /* Update profile_count by known autofdo count. */
1222 : : void
1223 : 0 : update_count_by_afdo_count (profile_count *count, gcov_type c)
1224 : : {
1225 : 0 : if (c)
1226 : 0 : *count = profile_count::from_gcov_type (c).afdo ();
1227 : : /* In case we have guessed profile which is already zero, preserve
1228 : : quality info. */
1229 : 0 : else if (count->nonzero_p ()
1230 : 0 : || count->quality () == GUESSED
1231 : 0 : || count->quality () == GUESSED_LOCAL)
1232 : 0 : *count = profile_count::zero ().afdo ();
1233 : 0 : }
1234 : :
1235 : : /* For a given BB, set its execution count. Attach value profile if a stmt
1236 : : is not in PROMOTED, because we only want to promote an indirect call once.
1237 : : Return TRUE if BB is annotated. */
1238 : :
1239 : : static bool
1240 : 0 : afdo_set_bb_count (basic_block bb)
1241 : : {
1242 : 0 : gimple_stmt_iterator gsi;
1243 : 0 : gcov_type max_count = 0;
1244 : 0 : bool has_annotated = false;
1245 : 0 : if (dump_file)
1246 : 0 : fprintf (dump_file, " Looking up AFDO count of bb %i\n", bb->index);
1247 : :
1248 : 0 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1249 : : {
1250 : 0 : count_info info;
1251 : 0 : gimple *stmt = gsi_stmt (gsi);
1252 : 0 : if (gimple_clobber_p (stmt) || is_gimple_debug (stmt))
1253 : 0 : continue;
1254 : 0 : if (afdo_source_profile->get_count_info (stmt, &info))
1255 : : {
1256 : 0 : if (info.count > max_count)
1257 : : max_count = info.count;
1258 : 0 : if (dump_file && info.count)
1259 : : {
1260 : 0 : fprintf (dump_file, " count %" PRIu64 " in stmt: ",
1261 : : (int64_t)info.count);
1262 : 0 : print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1263 : : }
1264 : 0 : has_annotated = true;
1265 : 0 : gcall *call = dyn_cast <gcall *> (gsi_stmt (gsi));
1266 : : /* TODO; if inlined early and indirect call was not optimized out,
1267 : : we will end up speculating again. Early inliner should remove
1268 : : all targets for edges it speculated into safely. */
1269 : 0 : if (call
1270 : 0 : && info.targets.size () > 0)
1271 : 0 : afdo_vpt (call, info.targets, false, NULL);
1272 : : }
1273 : 0 : }
1274 : :
1275 : 0 : if (!has_annotated)
1276 : : {
1277 : : /* For an empty BB with all debug stmt which assigne a value with
1278 : : constant, check successors PHIs corresponding to the block and
1279 : : use those counts. */
1280 : 0 : edge tmp_e;
1281 : 0 : edge_iterator tmp_ei;
1282 : 0 : FOR_EACH_EDGE (tmp_e, tmp_ei, bb->succs)
1283 : : {
1284 : 0 : basic_block bb_succ = tmp_e->dest;
1285 : 0 : for (gphi_iterator gpi = gsi_start_phis (bb_succ);
1286 : 0 : !gsi_end_p (gpi);
1287 : 0 : gsi_next (&gpi))
1288 : : {
1289 : 0 : gphi *phi = gpi.phi ();
1290 : 0 : location_t phi_loc
1291 : 0 : = gimple_phi_arg_location_from_edge (phi, tmp_e);
1292 : 0 : count_info info;
1293 : 0 : if (afdo_source_profile->get_count_info (phi_loc, &info)
1294 : 0 : && info.count != 0)
1295 : : {
1296 : 0 : if (info.count > max_count)
1297 : : max_count = info.count;
1298 : 0 : if (dump_file && info.count)
1299 : : {
1300 : 0 : fprintf (dump_file,
1301 : : " phi op in BB %i with count %" PRIu64": ",
1302 : : bb_succ->index, (int64_t)info.count);
1303 : 0 : print_gimple_stmt (dump_file, phi, 0, TDF_SLIM);
1304 : : }
1305 : : has_annotated = true;
1306 : : }
1307 : 0 : }
1308 : : }
1309 : :
1310 : 0 : if (!has_annotated)
1311 : 0 : return false;
1312 : : }
1313 : :
1314 : 0 : if (max_count)
1315 : : {
1316 : 0 : update_count_by_afdo_count (&bb->count, max_count);
1317 : 0 : if (dump_file)
1318 : 0 : fprintf (dump_file,
1319 : : " Annotated bb %i with count %" PRId64 "\n",
1320 : : bb->index, (int64_t)max_count);
1321 : 0 : return true;
1322 : : }
1323 : : return false;
1324 : : }
1325 : :
1326 : : /* BB1 and BB2 are in an equivalent class iff:
1327 : : 1. BB1 dominates BB2.
1328 : : 2. BB2 post-dominates BB1.
1329 : : 3. BB1 and BB2 are in the same loop nest.
1330 : : This function finds the equivalent class for each basic block, and
1331 : : stores a pointer to the first BB in its equivalent class. Meanwhile,
1332 : : set bb counts for the same equivalent class to be idenical. Update
1333 : : ANNOTATED_BB for the first BB in its equivalent class. */
1334 : :
1335 : : static void
1336 : 0 : afdo_find_equiv_class (bb_set *annotated_bb)
1337 : : {
1338 : 0 : basic_block bb;
1339 : :
1340 : 0 : FOR_ALL_BB_FN (bb, cfun)
1341 : 0 : bb->aux = NULL;
1342 : :
1343 : 0 : FOR_ALL_BB_FN (bb, cfun)
1344 : : {
1345 : 0 : if (bb->aux != NULL)
1346 : 0 : continue;
1347 : 0 : bb->aux = bb;
1348 : 0 : for (basic_block bb1 : get_dominated_by (CDI_DOMINATORS, bb))
1349 : 0 : if (bb1->aux == NULL && dominated_by_p (CDI_POST_DOMINATORS, bb, bb1)
1350 : 0 : && bb1->loop_father == bb->loop_father)
1351 : : {
1352 : 0 : bb1->aux = bb;
1353 : 0 : if (is_bb_annotated (bb1, *annotated_bb)
1354 : 0 : && (!is_bb_annotated (bb, *annotated_bb)
1355 : 0 : || bb1->count > bb->count))
1356 : : {
1357 : 0 : if (dump_file)
1358 : : {
1359 : 0 : fprintf (dump_file,
1360 : : " Copying count of bb %i to bb %i; count is:",
1361 : : bb1->index,
1362 : : bb->index);
1363 : 0 : bb1->count.dump (dump_file);
1364 : : }
1365 : 0 : bb->count = bb1->count;
1366 : 0 : set_bb_annotated (bb, annotated_bb);
1367 : : }
1368 : 0 : }
1369 : :
1370 : 0 : for (basic_block bb1 : get_dominated_by (CDI_POST_DOMINATORS, bb))
1371 : 0 : if (bb1->aux == NULL && dominated_by_p (CDI_DOMINATORS, bb, bb1)
1372 : 0 : && bb1->loop_father == bb->loop_father)
1373 : : {
1374 : 0 : bb1->aux = bb;
1375 : 0 : if (is_bb_annotated (bb1, *annotated_bb)
1376 : 0 : && (!is_bb_annotated (bb, *annotated_bb)
1377 : 0 : || bb1->count > bb->count))
1378 : : {
1379 : 0 : if (dump_file)
1380 : : {
1381 : 0 : fprintf (dump_file,
1382 : : " Copying count of bb %i to bb %i; count is:",
1383 : : bb1->index,
1384 : : bb->index);
1385 : 0 : bb1->count.dump (dump_file);
1386 : : }
1387 : 0 : bb->count = bb1->count;
1388 : 0 : set_bb_annotated (bb, annotated_bb);
1389 : : }
1390 : 0 : }
1391 : : }
1392 : 0 : }
1393 : :
1394 : : /* If a basic block's count is known, and only one of its in/out edges' count
1395 : : is unknown, its count can be calculated. Meanwhile, if all of the in/out
1396 : : edges' counts are known, then the basic block's unknown count can also be
1397 : : calculated. Also, if a block has a single predecessor or successor, the block's
1398 : : count can be propagated to that predecessor or successor.
1399 : : IS_SUCC is true if out edges of a basic blocks are examined.
1400 : : Update ANNOTATED_BB accordingly.
1401 : : Return TRUE if any basic block/edge count is changed. */
1402 : :
1403 : : static bool
1404 : 0 : afdo_propagate_edge (bool is_succ, bb_set *annotated_bb)
1405 : : {
1406 : 0 : basic_block bb;
1407 : 0 : bool changed = false;
1408 : :
1409 : 0 : FOR_EACH_BB_FN (bb, cfun)
1410 : : {
1411 : 0 : edge e, unknown_edge = NULL;
1412 : 0 : edge_iterator ei;
1413 : 0 : int num_unknown_edges = 0;
1414 : 0 : int num_edges = 0;
1415 : 0 : profile_count total_known_count = profile_count::zero ().afdo ();
1416 : :
1417 : 0 : FOR_EACH_EDGE (e, ei, is_succ ? bb->succs : bb->preds)
1418 : : {
1419 : 0 : gcc_assert (AFDO_EINFO (e) != NULL);
1420 : 0 : if (! AFDO_EINFO (e)->is_annotated ())
1421 : 0 : num_unknown_edges++, unknown_edge = e;
1422 : : else
1423 : 0 : total_known_count += AFDO_EINFO (e)->get_count ();
1424 : 0 : num_edges++;
1425 : : }
1426 : 0 : if (dump_file)
1427 : : {
1428 : 0 : fprintf (dump_file, "bb %i %s propagating %s edges %i, "
1429 : : "unknown edges %i, known count ",
1430 : : bb->index,
1431 : 0 : is_bb_annotated (bb, *annotated_bb) ? "(annotated)" : "",
1432 : : is_succ ? "succesors" : "predecessors", num_edges,
1433 : : num_unknown_edges);
1434 : 0 : total_known_count.dump (dump_file);
1435 : 0 : fprintf (dump_file, " bb count ");
1436 : 0 : bb->count.dump (dump_file);
1437 : 0 : fprintf (dump_file, "\n");
1438 : : }
1439 : :
1440 : : /* Be careful not to annotate block with no successor in special cases. */
1441 : 0 : if (num_unknown_edges == 0 && num_edges
1442 : 0 : && !is_bb_annotated (bb, *annotated_bb))
1443 : : {
1444 : 0 : if (dump_file)
1445 : : {
1446 : 0 : fprintf (dump_file, " Annotating bb %i with count ", bb->index);
1447 : 0 : total_known_count.dump (dump_file);
1448 : 0 : fprintf (dump_file, "\n");
1449 : : }
1450 : 0 : bb->count = total_known_count;
1451 : 0 : set_bb_annotated (bb, annotated_bb);
1452 : 0 : changed = true;
1453 : : }
1454 : 0 : else if (num_unknown_edges == 1 && is_bb_annotated (bb, *annotated_bb))
1455 : : {
1456 : 0 : if (bb->count > total_known_count)
1457 : : {
1458 : 0 : profile_count new_count = bb->count - total_known_count;
1459 : 0 : AFDO_EINFO (unknown_edge)->set_count (new_count);
1460 : : }
1461 : : else
1462 : 0 : AFDO_EINFO (unknown_edge)->set_count
1463 : 0 : (profile_count::zero ().afdo ());
1464 : 0 : if (dump_file)
1465 : : {
1466 : 0 : fprintf (dump_file, " Annotated edge %i->%i with count ",
1467 : 0 : unknown_edge->src->index, unknown_edge->dest->index);
1468 : 0 : AFDO_EINFO (unknown_edge)->get_count ().dump (dump_file);
1469 : 0 : fprintf (dump_file, "\n");
1470 : : }
1471 : 0 : AFDO_EINFO (unknown_edge)->set_annotated ();
1472 : 0 : changed = true;
1473 : : }
1474 : 0 : else if (num_unknown_edges > 1
1475 : 0 : && is_bb_annotated (bb, *annotated_bb)
1476 : 0 : && total_known_count >= bb->count)
1477 : : {
1478 : 0 : FOR_EACH_EDGE (e, ei, is_succ ? bb->succs : bb->preds)
1479 : : {
1480 : 0 : gcc_assert (AFDO_EINFO (e) != NULL);
1481 : 0 : if (! AFDO_EINFO (e)->is_annotated ())
1482 : : {
1483 : 0 : AFDO_EINFO (e)->set_count
1484 : 0 : (profile_count::zero ().afdo ());
1485 : 0 : AFDO_EINFO (e)->set_annotated ();
1486 : 0 : if (dump_file)
1487 : : {
1488 : 0 : fprintf (dump_file, " Annotated edge %i->%i with count ",
1489 : 0 : e->src->index, e->dest->index);
1490 : 0 : AFDO_EINFO (unknown_edge)->get_count ().dump (dump_file);
1491 : 0 : fprintf (dump_file, "\n");
1492 : : }
1493 : : }
1494 : : }
1495 : : }
1496 : : }
1497 : 0 : return changed;
1498 : : }
1499 : :
1500 : : /* Special propagation for circuit expressions. Because GCC translates
1501 : : control flow into data flow for circuit expressions. E.g.
1502 : : BB1:
1503 : : if (a && b)
1504 : : BB2
1505 : : else
1506 : : BB3
1507 : :
1508 : : will be translated into:
1509 : :
1510 : : BB1:
1511 : : if (a)
1512 : : goto BB.t1
1513 : : else
1514 : : goto BB.t3
1515 : : BB.t1:
1516 : : if (b)
1517 : : goto BB.t2
1518 : : else
1519 : : goto BB.t3
1520 : : BB.t2:
1521 : : goto BB.t3
1522 : : BB.t3:
1523 : : tmp = PHI (0 (BB1), 0 (BB.t1), 1 (BB.t2)
1524 : : if (tmp)
1525 : : goto BB2
1526 : : else
1527 : : goto BB3
1528 : :
1529 : : In this case, we need to propagate through PHI to determine the edge
1530 : : count of BB1->BB.t1, BB.t1->BB.t2. */
1531 : :
1532 : : static void
1533 : 0 : afdo_propagate_circuit (const bb_set &annotated_bb)
1534 : : {
1535 : 0 : basic_block bb;
1536 : 0 : FOR_ALL_BB_FN (bb, cfun)
1537 : : {
1538 : 0 : gimple *def_stmt;
1539 : 0 : tree cmp_rhs, cmp_lhs;
1540 : 0 : gimple *cmp_stmt = last_nondebug_stmt (bb);
1541 : 0 : edge e;
1542 : 0 : edge_iterator ei;
1543 : :
1544 : 0 : if (!cmp_stmt || gimple_code (cmp_stmt) != GIMPLE_COND)
1545 : 0 : continue;
1546 : 0 : cmp_rhs = gimple_cond_rhs (cmp_stmt);
1547 : 0 : cmp_lhs = gimple_cond_lhs (cmp_stmt);
1548 : 0 : if (!TREE_CONSTANT (cmp_rhs)
1549 : 0 : || !(integer_zerop (cmp_rhs) || integer_onep (cmp_rhs)))
1550 : 0 : continue;
1551 : 0 : if (TREE_CODE (cmp_lhs) != SSA_NAME)
1552 : 0 : continue;
1553 : 0 : if (!is_bb_annotated (bb, annotated_bb))
1554 : 0 : continue;
1555 : 0 : def_stmt = SSA_NAME_DEF_STMT (cmp_lhs);
1556 : 0 : while (def_stmt && gimple_code (def_stmt) == GIMPLE_ASSIGN
1557 : 0 : && gimple_assign_single_p (def_stmt)
1558 : 0 : && TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME)
1559 : 0 : def_stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def_stmt));
1560 : 0 : if (!def_stmt)
1561 : 0 : continue;
1562 : 0 : gphi *phi_stmt = dyn_cast <gphi *> (def_stmt);
1563 : 0 : if (!phi_stmt)
1564 : 0 : continue;
1565 : 0 : FOR_EACH_EDGE (e, ei, bb->succs)
1566 : : {
1567 : 0 : unsigned i, total = 0;
1568 : 0 : edge only_one;
1569 : 0 : bool check_value_one = (((integer_onep (cmp_rhs))
1570 : 0 : ^ (gimple_cond_code (cmp_stmt) == EQ_EXPR))
1571 : 0 : ^ ((e->flags & EDGE_TRUE_VALUE) != 0));
1572 : 0 : if (! AFDO_EINFO (e)->is_annotated ())
1573 : 0 : continue;
1574 : 0 : for (i = 0; i < gimple_phi_num_args (phi_stmt); i++)
1575 : : {
1576 : 0 : tree val = gimple_phi_arg_def (phi_stmt, i);
1577 : 0 : edge ep = gimple_phi_arg_edge (phi_stmt, i);
1578 : :
1579 : 0 : if (!TREE_CONSTANT (val)
1580 : 0 : || !(integer_zerop (val) || integer_onep (val)))
1581 : 0 : continue;
1582 : 0 : if (check_value_one ^ integer_onep (val))
1583 : 0 : continue;
1584 : 0 : total++;
1585 : 0 : only_one = ep;
1586 : 0 : if (! (AFDO_EINFO (e)->get_count ()).nonzero_p ()
1587 : 0 : && ! AFDO_EINFO (ep)->is_annotated ())
1588 : : {
1589 : 0 : AFDO_EINFO (ep)->set_count (profile_count::zero ().afdo ());
1590 : 0 : AFDO_EINFO (ep)->set_annotated ();
1591 : : }
1592 : : }
1593 : 0 : if (total == 1 && ! AFDO_EINFO (only_one)->is_annotated ())
1594 : : {
1595 : 0 : AFDO_EINFO (only_one)->set_count (AFDO_EINFO (e)->get_count ());
1596 : 0 : AFDO_EINFO (only_one)->set_annotated ();
1597 : : }
1598 : : }
1599 : : }
1600 : 0 : }
1601 : :
1602 : : /* Propagate the basic block count and edge count on the control flow
1603 : : graph. We do the propagation iteratively until stablize. */
1604 : :
1605 : : static void
1606 : 0 : afdo_propagate (bb_set *annotated_bb)
1607 : : {
1608 : 0 : bool changed = true;
1609 : 0 : int i = 0;
1610 : :
1611 : 0 : basic_block bb;
1612 : 0 : FOR_ALL_BB_FN (bb, cfun)
1613 : 0 : if (!is_bb_annotated (bb, *annotated_bb)
1614 : 0 : && is_bb_annotated ((basic_block)bb->aux, *annotated_bb))
1615 : : {
1616 : 0 : bb->count = ((basic_block)bb->aux)->count;
1617 : 0 : set_bb_annotated (bb, annotated_bb);
1618 : 0 : if (dump_file)
1619 : : {
1620 : 0 : fprintf (dump_file,
1621 : : " Copying count of bb %i to bb %i; count is:",
1622 : 0 : ((basic_block)bb->aux)->index,
1623 : : bb->index);
1624 : 0 : bb->count.dump (dump_file);
1625 : : }
1626 : : }
1627 : :
1628 : 0 : while (changed && i++ < 10)
1629 : : {
1630 : 0 : changed = false;
1631 : :
1632 : 0 : if (afdo_propagate_edge (true, annotated_bb))
1633 : : changed = true;
1634 : 0 : if (afdo_propagate_edge (false, annotated_bb))
1635 : 0 : changed = true;
1636 : 0 : afdo_propagate_circuit (*annotated_bb);
1637 : : }
1638 : 0 : if (dump_file)
1639 : 0 : fprintf (dump_file, "Propated in %i iterations %s\n",
1640 : : i, changed ? "; iteration limit reached\n" : "");
1641 : 0 : }
1642 : :
1643 : : /* qsort comparator of sreals. */
1644 : : static int
1645 : 0 : cmp (const void *a, const void *b)
1646 : : {
1647 : 0 : if (*(const sreal *)a < *(const sreal *)b)
1648 : : return 1;
1649 : 0 : if (*(const sreal *)a > *(const sreal *)b)
1650 : 0 : return -1;
1651 : : return 0;
1652 : : }
1653 : :
1654 : : /* Add scale ORIG/ANNOTATED to SCALES. */
1655 : :
1656 : : static void
1657 : 0 : add_scale (vec <sreal> *scales, profile_count annotated, profile_count orig)
1658 : : {
1659 : 0 : if (dump_file)
1660 : : {
1661 : 0 : orig.dump (dump_file);
1662 : 0 : fprintf (dump_file, " should be ");
1663 : 0 : annotated.dump (dump_file);
1664 : 0 : fprintf (dump_file, "\n");
1665 : : }
1666 : 0 : if (orig.nonzero_p ())
1667 : : {
1668 : 0 : sreal scale
1669 : 0 : = annotated.guessed_local ()
1670 : 0 : .to_sreal_scale (orig);
1671 : 0 : if (dump_file)
1672 : 0 : fprintf (dump_file, " adding scale %.16f\n",
1673 : : scale.to_double ());
1674 : 0 : scales->safe_push (scale);
1675 : : }
1676 : 0 : }
1677 : :
1678 : : /* Scale counts of all basic blocks in BBS by SCALE and convert them to
1679 : : IPA quality. */
1680 : :
1681 : : static void
1682 : 0 : scale_bbs (const vec <basic_block> &bbs, sreal scale)
1683 : : {
1684 : 0 : if (dump_file)
1685 : 0 : fprintf (dump_file, " Scaling by %.16f\n", scale.to_double ());
1686 : 0 : for (basic_block b : bbs)
1687 : 0 : if (!(b->count == profile_count::zero ())
1688 : 0 : && b->count.initialized_p ())
1689 : : {
1690 : 0 : profile_count o = b->count;
1691 : 0 : b->count = b->count.force_guessed () * scale;
1692 : :
1693 : : /* If we scaled to 0, make it auto-fdo since that is treated
1694 : : less agressively. */
1695 : 0 : if (!b->count.nonzero_p () && o.nonzero_p ())
1696 : 0 : b->count = profile_count::zero ().afdo ();
1697 : 0 : if (dump_file)
1698 : : {
1699 : 0 : fprintf (dump_file, " bb %i count updated ", b->index);
1700 : 0 : o.dump (dump_file);
1701 : 0 : fprintf (dump_file, " -> ");
1702 : 0 : b->count.dump (dump_file);
1703 : 0 : fprintf (dump_file, "\n");
1704 : : }
1705 : : }
1706 : 0 : }
1707 : :
1708 : : /* In case given basic block was fully optimized out, AutoFDO
1709 : : will have no data about it. In this case try to preserve static profile.
1710 : : Identify connected components (in undirected form of CFG) which has
1711 : : no annotations at all. Look at thir boundaries and try to determine
1712 : : scaling factor and scale. */
1713 : :
1714 : : void
1715 : 0 : afdo_adjust_guessed_profile (bb_set *annotated_bb)
1716 : : {
1717 : : /* Basic blocks of connected component currently processed. */
1718 : 0 : auto_vec <basic_block, 20> bbs (n_basic_blocks_for_fn (cfun));
1719 : : /* Scale factors found. */
1720 : 0 : auto_vec <sreal, 20> scales;
1721 : 0 : auto_vec <basic_block, 20> stack (n_basic_blocks_for_fn (cfun));
1722 : :
1723 : 0 : basic_block seed_bb;
1724 : 0 : unsigned int component_id = 1;
1725 : :
1726 : : /* Map from basic block to its component.
1727 : : 0 is used for univisited BBs,
1728 : : 1 means that BB is annotated,
1729 : : >=2 is an id of the component BB belongs to. */
1730 : 0 : auto_vec <unsigned int, 20> component;
1731 : 0 : component.safe_grow (last_basic_block_for_fn (cfun));
1732 : 0 : FOR_ALL_BB_FN (seed_bb, cfun)
1733 : 0 : component[seed_bb->index]
1734 : 0 : = is_bb_annotated (seed_bb, *annotated_bb) ? 1 : 0;
1735 : 0 : FOR_ALL_BB_FN (seed_bb, cfun)
1736 : 0 : if (!component[seed_bb->index])
1737 : : {
1738 : 0 : stack.quick_push (seed_bb);
1739 : 0 : component_id++;
1740 : 0 : bbs.truncate (0);
1741 : 0 : scales.truncate (0);
1742 : 0 : component[seed_bb->index] = component_id;
1743 : 0 : profile_count max_count = profile_count::zero ();
1744 : :
1745 : : /* Identify connected component starting in BB. */
1746 : 0 : if (dump_file)
1747 : 0 : fprintf (dump_file, "Starting connected component in bb %i\n",
1748 : : seed_bb->index);
1749 : 0 : do
1750 : : {
1751 : 0 : basic_block b = stack.pop ();
1752 : :
1753 : 0 : bbs.quick_push (b);
1754 : 0 : max_count = max_count.max (b->count);
1755 : :
1756 : 0 : for (edge e: b->preds)
1757 : 0 : if (!component[e->src->index])
1758 : : {
1759 : 0 : stack.quick_push (e->src);
1760 : 0 : component[e->src->index] = component_id;
1761 : : }
1762 : 0 : for (edge e: b->succs)
1763 : 0 : if (!component[e->dest->index])
1764 : : {
1765 : 0 : stack.quick_push (e->dest);
1766 : 0 : component[e->dest->index] = component_id;
1767 : : }
1768 : : }
1769 : 0 : while (!stack.is_empty ());
1770 : :
1771 : : /* If all blocks in components has 0 count, we do not need
1772 : : to scale, only we must convert to IPA quality. */
1773 : 0 : if (!max_count.nonzero_p ())
1774 : : {
1775 : 0 : if (dump_file)
1776 : 0 : fprintf (dump_file, " All counts are 0; scale = 1\n");
1777 : 0 : scale_bbs (bbs, 1);
1778 : 0 : continue;
1779 : : }
1780 : :
1781 : : /* Now visit the component and try to figure out its desired
1782 : : frequency. */
1783 : 0 : for (basic_block b : bbs)
1784 : : {
1785 : 0 : if (dump_file)
1786 : : {
1787 : 0 : fprintf (dump_file, " visiting bb %i with count ", b->index);
1788 : 0 : b->count.dump (dump_file);
1789 : 0 : fprintf (dump_file, "\n");
1790 : : }
1791 : 0 : if (!b->count.nonzero_p ())
1792 : 0 : continue;
1793 : : /* Sum of counts of annotated edges into B. */
1794 : 0 : profile_count annotated_count = profile_count::zero ();
1795 : : /* Sum of counts of edges into B with source in current
1796 : : component. */
1797 : 0 : profile_count current_component_count = profile_count::zero ();
1798 : 0 : bool boundary = false;
1799 : :
1800 : 0 : for (edge e: b->preds)
1801 : 0 : if (AFDO_EINFO (e)->is_annotated ())
1802 : : {
1803 : 0 : if (dump_file)
1804 : : {
1805 : 0 : fprintf (dump_file, " Annotated pred edge to %i "
1806 : 0 : "with count ", e->src->index);
1807 : 0 : AFDO_EINFO (e)->get_count ().dump (dump_file);
1808 : 0 : fprintf (dump_file, "\n");
1809 : : }
1810 : 0 : boundary = true;
1811 : 0 : annotated_count += AFDO_EINFO (e)->get_count ();
1812 : : }
1813 : : /* If source is anotated, combine with static
1814 : : probability prediction.
1815 : : TODO: We can do better in case some of edges out are
1816 : : annotated and distribute only remaining count out of BB. */
1817 : 0 : else if (is_bb_annotated (e->src, *annotated_bb))
1818 : : {
1819 : 0 : boundary = true;
1820 : 0 : if (dump_file)
1821 : : {
1822 : 0 : fprintf (dump_file, " Annotated predecesor %i "
1823 : : "with count ", e->src->index);
1824 : 0 : e->src->count.dump (dump_file);
1825 : 0 : fprintf (dump_file, " edge count using static profile ");
1826 : 0 : e->count ().dump (dump_file);
1827 : 0 : fprintf (dump_file, "\n");
1828 : : }
1829 : 0 : annotated_count += e->count ();
1830 : : }
1831 : : else
1832 : : {
1833 : 0 : current_component_count += e->count ();
1834 : 0 : gcc_checking_assert (component[e->src->index] == component_id);
1835 : : }
1836 : 0 : if (boundary && current_component_count.initialized_p ())
1837 : : {
1838 : 0 : if (dump_file)
1839 : 0 : fprintf (dump_file, " bb %i in count ", b->index);
1840 : 0 : add_scale (&scales,
1841 : : annotated_count,
1842 : : b->count - current_component_count);
1843 : : }
1844 : 0 : for (edge e: b->succs)
1845 : 0 : if (AFDO_EINFO (e)->is_annotated ())
1846 : : {
1847 : 0 : if (dump_file)
1848 : 0 : fprintf (dump_file, " edge %i->%i count ",
1849 : 0 : b->index, e->dest->index);
1850 : 0 : add_scale (&scales, AFDO_EINFO (e)->get_count (), e->count ());
1851 : : }
1852 : 0 : else if (is_bb_annotated (e->dest, *annotated_bb))
1853 : : {
1854 : 0 : profile_count annotated_count = e->dest->count;
1855 : 0 : profile_count out_count = profile_count::zero ();
1856 : 0 : bool ok = true;
1857 : 0 : for (edge e2: e->dest->preds)
1858 : 0 : if (AFDO_EINFO (e2)->is_annotated ())
1859 : 0 : annotated_count -= AFDO_EINFO (e2)->get_count ();
1860 : 0 : else if (component[e->src->index] == component_id)
1861 : 0 : out_count += e->count ();
1862 : 0 : else if (e->probability.nonzero_p ())
1863 : : {
1864 : : ok = false;
1865 : : break;
1866 : : }
1867 : 0 : if (!ok)
1868 : 0 : continue;
1869 : 0 : if (dump_file)
1870 : 0 : fprintf (dump_file,
1871 : : " edge %i->%i has annotated sucessor; count ",
1872 : 0 : b->index, e->dest->index);
1873 : 0 : add_scale (&scales, annotated_count, e->count ());
1874 : : }
1875 : :
1876 : : }
1877 : :
1878 : : /* If we failed to find annotated entry or exit edge,
1879 : : look for exit edges and scale profile so the dest
1880 : : BB get all flow it needs. This is inprecise because
1881 : : the edge is not annotated and thus BB has more than
1882 : : one such predecessor. */
1883 : 0 : if (!scales.length ())
1884 : 0 : for (basic_block b : bbs)
1885 : 0 : if (b->count.nonzero_p ())
1886 : 0 : for (edge e: b->succs)
1887 : 0 : if (is_bb_annotated (e->dest, *annotated_bb))
1888 : : {
1889 : 0 : profile_count annotated_count = e->dest->count;
1890 : 0 : for (edge e2: e->dest->preds)
1891 : 0 : if (AFDO_EINFO (e2)->is_annotated ())
1892 : 0 : annotated_count -= AFDO_EINFO (e2)->get_count ();
1893 : 0 : if (dump_file)
1894 : 0 : fprintf (dump_file,
1895 : : " edge %i->%i has annotated sucessor;"
1896 : : " upper bound count ",
1897 : 0 : b->index, e->dest->index);
1898 : 0 : add_scale (&scales, annotated_count, e->count ());
1899 : : }
1900 : 0 : if (!scales.length ())
1901 : : {
1902 : 0 : if (dump_file)
1903 : 0 : fprintf (dump_file,
1904 : : " Can not determine count from the boundary; giving up");
1905 : 0 : continue;
1906 : : }
1907 : 0 : gcc_checking_assert (scales.length ());
1908 : 0 : scales.qsort (cmp);
1909 : 0 : scale_bbs (bbs, scales[scales.length () / 2]);
1910 : : }
1911 : 0 : }
1912 : :
1913 : : /* Propagate counts on control flow graph and calculate branch
1914 : : probabilities. */
1915 : :
1916 : : static void
1917 : 0 : afdo_calculate_branch_prob (bb_set *annotated_bb)
1918 : : {
1919 : 0 : edge e;
1920 : 0 : edge_iterator ei;
1921 : 0 : basic_block bb;
1922 : :
1923 : 0 : FOR_ALL_BB_FN (bb, cfun)
1924 : : {
1925 : 0 : gcc_assert (bb->aux == NULL);
1926 : 0 : FOR_EACH_EDGE (e, ei, bb->succs)
1927 : : {
1928 : 0 : gcc_assert (e->aux == NULL);
1929 : 0 : e->aux = new edge_info ();
1930 : : }
1931 : : }
1932 : :
1933 : 0 : afdo_find_equiv_class (annotated_bb);
1934 : 0 : afdo_propagate (annotated_bb);
1935 : :
1936 : 0 : FOR_EACH_BB_FN (bb, cfun)
1937 : 0 : if (is_bb_annotated (bb, *annotated_bb))
1938 : : {
1939 : 0 : bool all_known = false;
1940 : 0 : profile_count total_count = profile_count::zero ().afdo ();
1941 : :
1942 : 0 : FOR_EACH_EDGE (e, ei, bb->succs)
1943 : : {
1944 : 0 : gcc_assert (AFDO_EINFO (e) != NULL);
1945 : 0 : if (! AFDO_EINFO (e)->is_annotated ())
1946 : : {
1947 : : /* If by static profile this edge never happens,
1948 : : still propagate the rest. */
1949 : 0 : if (e->probability.nonzero_p ())
1950 : : {
1951 : : all_known = true;
1952 : : break;
1953 : : }
1954 : : }
1955 : : else
1956 : 0 : total_count += AFDO_EINFO (e)->get_count ();
1957 : : }
1958 : 0 : if (!all_known || !total_count.nonzero_p ())
1959 : 0 : continue;
1960 : :
1961 : 0 : FOR_EACH_EDGE (e, ei, bb->succs)
1962 : 0 : if (AFDO_EINFO (e)->is_annotated ())
1963 : : {
1964 : : /* If probability is 1, preserve reliable static prediction
1965 : : (This is, for example the case of single fallthru edge
1966 : : or single fallthru plus unlikely EH edge.) */
1967 : 0 : if (AFDO_EINFO (e)->get_count () == total_count
1968 : 0 : && e->probability == profile_probability::always ())
1969 : : ;
1970 : 0 : else if (AFDO_EINFO (e)->get_count ().nonzero_p ())
1971 : 0 : e->probability
1972 : 0 : = AFDO_EINFO (e)->get_count ().probability_in (total_count);
1973 : : /* If probability is zero, preserve reliable static
1974 : : prediction. */
1975 : 0 : else if (e->probability.nonzero_p ()
1976 : 0 : || e->probability.quality () == GUESSED)
1977 : 0 : e->probability = profile_probability::never ().afdo ();
1978 : : }
1979 : : }
1980 : 0 : afdo_adjust_guessed_profile (annotated_bb);
1981 : 0 : FOR_ALL_BB_FN (bb, cfun)
1982 : : {
1983 : 0 : bb->aux = NULL;
1984 : 0 : FOR_EACH_EDGE (e, ei, bb->succs)
1985 : 0 : if (AFDO_EINFO (e) != NULL)
1986 : : {
1987 : 0 : delete AFDO_EINFO (e);
1988 : 0 : e->aux = NULL;
1989 : : }
1990 : : }
1991 : 0 : }
1992 : :
1993 : : /* Annotate auto profile to the control flow graph. */
1994 : :
1995 : : static void
1996 : 0 : afdo_annotate_cfg (void)
1997 : : {
1998 : 0 : basic_block bb;
1999 : 0 : bb_set annotated_bb;
2000 : 0 : const function_instance *s
2001 : 0 : = afdo_source_profile->get_function_instance_by_decl (
2002 : : current_function_decl);
2003 : :
2004 : 0 : if (s == NULL)
2005 : : {
2006 : 0 : if (dump_file)
2007 : 0 : fprintf (dump_file, "No afdo profile for %s",
2008 : 0 : cgraph_node::get (current_function_decl)->dump_name ());
2009 : 0 : return;
2010 : : }
2011 : :
2012 : 0 : calculate_dominance_info (CDI_POST_DOMINATORS);
2013 : 0 : calculate_dominance_info (CDI_DOMINATORS);
2014 : 0 : loop_optimizer_init (0);
2015 : :
2016 : 0 : if (dump_file)
2017 : 0 : fprintf (dump_file, "\n\nAnnotating BB profile of %s\n",
2018 : 0 : cgraph_node::get (current_function_decl)->dump_name ());
2019 : :
2020 : : /* In the first pass only store non-zero counts. */
2021 : 0 : gcov_type head_count = s->head_count ();
2022 : 0 : bool profile_found = head_count > 0;
2023 : 0 : FOR_EACH_BB_FN (bb, cfun)
2024 : : {
2025 : 0 : if (afdo_set_bb_count (bb))
2026 : : {
2027 : 0 : if (bb->count.quality () == AFDO)
2028 : : {
2029 : 0 : gcc_assert (bb->count.nonzero_p ());
2030 : : profile_found = true;
2031 : : }
2032 : 0 : set_bb_annotated (bb, &annotated_bb);
2033 : : }
2034 : : }
2035 : : /* Exit without clobbering static profile if there was no
2036 : : non-zero count.
2037 : : ??? Instead of keeping guessed profile we can introduce
2038 : : GUESSED_GLOBAL0_AFDO. */
2039 : 0 : if (!profile_found)
2040 : : {
2041 : 0 : if (dump_file)
2042 : 0 : fprintf (dump_file, "No afdo samples found"
2043 : : "; keeping original profile\n");
2044 : :
2045 : 0 : loop_optimizer_finalize ();
2046 : 0 : free_dominance_info (CDI_DOMINATORS);
2047 : 0 : free_dominance_info (CDI_POST_DOMINATORS);
2048 : 0 : return;
2049 : : }
2050 : :
2051 : : /* Update profile. */
2052 : 0 : if (head_count)
2053 : : {
2054 : 0 : update_count_by_afdo_count (&ENTRY_BLOCK_PTR_FOR_FN (cfun)->count,
2055 : : head_count);
2056 : 0 : set_bb_annotated (ENTRY_BLOCK_PTR_FOR_FN (cfun), &annotated_bb);
2057 : 0 : if (!is_bb_annotated (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb, annotated_bb)
2058 : 0 : || ENTRY_BLOCK_PTR_FOR_FN (cfun)->count
2059 : 0 : > ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb->count)
2060 : : {
2061 : 0 : ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb->count
2062 : 0 : = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
2063 : 0 : set_bb_annotated (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb,
2064 : : &annotated_bb);
2065 : : }
2066 : 0 : if (!is_bb_annotated (EXIT_BLOCK_PTR_FOR_FN (cfun), annotated_bb)
2067 : 0 : || ENTRY_BLOCK_PTR_FOR_FN (cfun)->count
2068 : 0 : > EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb->count)
2069 : : {
2070 : 0 : EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb->count
2071 : 0 : = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
2072 : 0 : set_bb_annotated (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb, &annotated_bb);
2073 : : }
2074 : : }
2075 : :
2076 : : /* Calculate, propagate count and probability information on CFG. */
2077 : 0 : afdo_calculate_branch_prob (&annotated_bb);
2078 : :
2079 : : /* If we failed to turn some of original guessed profile to global,
2080 : : set basic blocks uninitialized. */
2081 : 0 : FOR_ALL_BB_FN (bb, cfun)
2082 : 0 : if (!bb->count.ipa_p ())
2083 : : {
2084 : : /* We skip annotating entry profile if it is 0
2085 : : in hope to be able to determine it better from the
2086 : : static profile.
2087 : :
2088 : : Now we know we can not derive it from other info,
2089 : : so set it since it is better than UNKNOWN. */
2090 : 0 : if (bb == ENTRY_BLOCK_PTR_FOR_FN (cfun))
2091 : 0 : bb->count = profile_count::zero ().afdo ();
2092 : : else
2093 : 0 : bb->count = profile_count::uninitialized ();
2094 : 0 : if (dump_file)
2095 : 0 : fprintf (dump_file, " Unknown count of bb %i\n", bb->index);
2096 : 0 : cfun->cfg->full_profile = false;
2097 : : }
2098 : :
2099 : 0 : cgraph_node::get(current_function_decl)->count
2100 : 0 : = ENTRY_BLOCK_PTR_FOR_FN(cfun)->count;
2101 : 0 : update_max_bb_count ();
2102 : 0 : profile_status_for_fn (cfun) = PROFILE_READ;
2103 : 0 : if (flag_value_profile_transformations)
2104 : : {
2105 : 0 : gimple_value_profile_transformations ();
2106 : 0 : free_dominance_info (CDI_DOMINATORS);
2107 : 0 : free_dominance_info (CDI_POST_DOMINATORS);
2108 : 0 : update_ssa (TODO_update_ssa);
2109 : : }
2110 : :
2111 : 0 : loop_optimizer_finalize ();
2112 : 0 : free_dominance_info (CDI_DOMINATORS);
2113 : 0 : free_dominance_info (CDI_POST_DOMINATORS);
2114 : 0 : }
2115 : :
2116 : : /* Wrapper function to invoke early inliner. */
2117 : :
2118 : : static unsigned int
2119 : 0 : early_inline ()
2120 : : {
2121 : 0 : compute_fn_summary (cgraph_node::get (current_function_decl), true);
2122 : 0 : unsigned int todo = early_inliner (cfun);
2123 : 0 : if (todo & TODO_update_ssa_any)
2124 : 0 : update_ssa (TODO_update_ssa);
2125 : 0 : return todo;
2126 : : }
2127 : :
2128 : : /* Use AutoFDO profile to annoate the control flow graph.
2129 : : Return the todo flag. */
2130 : :
2131 : : static unsigned int
2132 : 0 : auto_profile (void)
2133 : : {
2134 : 0 : struct cgraph_node *node;
2135 : :
2136 : 0 : if (symtab->state == FINISHED)
2137 : : return 0;
2138 : :
2139 : 0 : init_node_map (true);
2140 : 0 : profile_info = autofdo::afdo_profile_info;
2141 : :
2142 : 0 : FOR_EACH_FUNCTION (node)
2143 : : {
2144 : 0 : if (!gimple_has_body_p (node->decl))
2145 : 0 : continue;
2146 : :
2147 : : /* Don't profile functions produced for builtin stuff. */
2148 : 0 : if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
2149 : 0 : continue;
2150 : :
2151 : 0 : push_cfun (DECL_STRUCT_FUNCTION (node->decl));
2152 : :
2153 : 0 : unsigned int todo = early_inline ();
2154 : 0 : autofdo::afdo_annotate_cfg ();
2155 : 0 : compute_function_frequency ();
2156 : :
2157 : : /* Local pure-const may imply need to fixup the cfg. */
2158 : 0 : todo |= execute_fixup_cfg ();
2159 : 0 : if (todo & TODO_cleanup_cfg)
2160 : 0 : cleanup_tree_cfg ();
2161 : :
2162 : 0 : free_dominance_info (CDI_DOMINATORS);
2163 : 0 : free_dominance_info (CDI_POST_DOMINATORS);
2164 : 0 : cgraph_edge::rebuild_edges ();
2165 : 0 : compute_fn_summary (cgraph_node::get (current_function_decl), true);
2166 : 0 : pop_cfun ();
2167 : : }
2168 : :
2169 : : return 0;
2170 : : }
2171 : : } /* namespace autofdo. */
2172 : :
2173 : : /* Read the profile from the profile data file. */
2174 : :
2175 : : void
2176 : 0 : read_autofdo_file (void)
2177 : : {
2178 : 0 : if (auto_profile_file == NULL)
2179 : 0 : auto_profile_file = DEFAULT_AUTO_PROFILE_FILE;
2180 : :
2181 : 0 : autofdo::afdo_profile_info = XNEW (gcov_summary);
2182 : 0 : autofdo::afdo_profile_info->runs = 1;
2183 : 0 : autofdo::afdo_profile_info->sum_max = 0;
2184 : :
2185 : : /* Read the profile from the profile file. */
2186 : 0 : autofdo::read_profile ();
2187 : 0 : }
2188 : :
2189 : : /* Free the resources. */
2190 : :
2191 : : void
2192 : 0 : end_auto_profile (void)
2193 : : {
2194 : 0 : delete autofdo::afdo_source_profile;
2195 : 0 : delete autofdo::afdo_string_table;
2196 : 0 : profile_info = NULL;
2197 : 0 : }
2198 : :
2199 : : /* Returns TRUE if EDGE is hot enough to be inlined early. */
2200 : :
2201 : : bool
2202 : 0 : afdo_callsite_hot_enough_for_early_inline (struct cgraph_edge *edge)
2203 : : {
2204 : 0 : gcov_type count
2205 : 0 : = autofdo::afdo_source_profile->get_callsite_total_count (edge);
2206 : :
2207 : 0 : if (count > 0)
2208 : : {
2209 : 0 : bool is_hot;
2210 : 0 : profile_count pcount = profile_count::from_gcov_type (count).afdo ();
2211 : 0 : gcov_summary *saved_profile_info = profile_info;
2212 : : /* At early inline stage, profile_info is not set yet. We need to
2213 : : temporarily set it to afdo_profile_info to calculate hotness. */
2214 : 0 : profile_info = autofdo::afdo_profile_info;
2215 : 0 : is_hot = maybe_hot_count_p (NULL, pcount);
2216 : 0 : if (dump_file)
2217 : : {
2218 : 0 : fprintf (dump_file, "Call %s -> %s has %s afdo profile count ",
2219 : 0 : edge->caller->dump_name (), edge->callee->dump_name (),
2220 : : is_hot ? "hot" : "cold");
2221 : 0 : pcount.dump (dump_file);
2222 : 0 : fprintf (dump_file, "\n");
2223 : : }
2224 : 0 : profile_info = saved_profile_info;
2225 : 0 : return is_hot;
2226 : : }
2227 : :
2228 : : return false;
2229 : : }
2230 : :
2231 : : /* Do indirect call promotion during early inlining to make the
2232 : : IR match the profiled binary before actual annotation.
2233 : :
2234 : : This is needed because an indirect call might have been promoted
2235 : : and inlined in the profiled binary. If we do not promote and
2236 : : inline these indirect calls before annotation, the profile for
2237 : : these promoted functions will be lost.
2238 : :
2239 : : e.g. foo() --indirect_call--> bar()
2240 : : In profiled binary, the callsite is promoted and inlined, making
2241 : : the profile look like:
2242 : :
2243 : : foo: {
2244 : : loc_foo_1: count_1
2245 : : bar@loc_foo_2: {
2246 : : loc_bar_1: count_2
2247 : : loc_bar_2: count_3
2248 : : }
2249 : : }
2250 : :
2251 : : Before AutoFDO pass, loc_foo_2 is not promoted thus not inlined.
2252 : : If we perform annotation on it, the profile inside bar@loc_foo2
2253 : : will be wasted.
2254 : :
2255 : : To avoid this, we promote loc_foo_2 and inline the promoted bar
2256 : : function before annotation, so the profile inside bar@loc_foo2
2257 : : will be useful. */
2258 : :
2259 : : bool
2260 : 0 : afdo_vpt_for_early_inline (cgraph_node *node)
2261 : : {
2262 : 0 : if (!node->indirect_calls)
2263 : : return false;
2264 : 0 : bool changed = false;
2265 : 0 : cgraph_node *outer = node->inlined_to ? node->inlined_to : node;
2266 : 0 : if (autofdo::afdo_source_profile->get_function_instance_by_decl
2267 : 0 : (outer->decl) == NULL)
2268 : : return false;
2269 : 0 : for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
2270 : : {
2271 : 0 : gcov_type bb_count = 0;
2272 : 0 : autofdo::count_info info;
2273 : 0 : basic_block bb = gimple_bb (e->call_stmt);
2274 : :
2275 : : /* TODO: This is quadratic; cache the value. */
2276 : 0 : for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
2277 : 0 : !gsi_end_p (gsi); gsi_next (&gsi))
2278 : : {
2279 : 0 : autofdo::count_info info;
2280 : 0 : gimple *stmt = gsi_stmt (gsi);
2281 : 0 : if (autofdo::afdo_source_profile->get_count_info (stmt, &info, node))
2282 : 0 : bb_count = MAX (bb_count, info.count);
2283 : 0 : }
2284 : 0 : autofdo::afdo_source_profile->get_count_info (e->call_stmt, &info, node);
2285 : 0 : info.count = bb_count;
2286 : 0 : if (!autofdo::afdo_source_profile->update_inlined_ind_target
2287 : 0 : (e->call_stmt, &info, node))
2288 : 0 : continue;
2289 : 0 : changed |= autofdo::afdo_vpt (e->call_stmt, info.targets, true, e);
2290 : 0 : }
2291 : : return changed;
2292 : : }
2293 : :
2294 : : /* If speculation used during early inline, remove the target
2295 : : so we do not speculate the indirect edge again during afdo pass. */
2296 : :
2297 : : void
2298 : 0 : remove_afdo_speculative_target (cgraph_edge *e)
2299 : : {
2300 : 0 : autofdo::afdo_source_profile->remove_icall_target (e);
2301 : 0 : }
2302 : :
2303 : : namespace
2304 : : {
2305 : :
2306 : : const pass_data pass_data_ipa_auto_profile = {
2307 : : SIMPLE_IPA_PASS, "afdo", /* name */
2308 : : OPTGROUP_NONE, /* optinfo_flags */
2309 : : TV_IPA_AUTOFDO, /* tv_id */
2310 : : 0, /* properties_required */
2311 : : 0, /* properties_provided */
2312 : : 0, /* properties_destroyed */
2313 : : 0, /* todo_flags_start */
2314 : : 0, /* todo_flags_finish */
2315 : : };
2316 : :
2317 : : class pass_ipa_auto_profile : public simple_ipa_opt_pass
2318 : : {
2319 : : public:
2320 : 285081 : pass_ipa_auto_profile (gcc::context *ctxt)
2321 : 570162 : : simple_ipa_opt_pass (pass_data_ipa_auto_profile, ctxt)
2322 : : {
2323 : : }
2324 : :
2325 : : /* opt_pass methods: */
2326 : : bool
2327 : 228759 : gate (function *) final override
2328 : : {
2329 : 228759 : return flag_auto_profile;
2330 : : }
2331 : : unsigned int
2332 : 0 : execute (function *) final override
2333 : : {
2334 : 0 : return autofdo::auto_profile ();
2335 : : }
2336 : : }; // class pass_ipa_auto_profile
2337 : :
2338 : : } // anon namespace
2339 : :
2340 : : simple_ipa_opt_pass *
2341 : 285081 : make_pass_ipa_auto_profile (gcc::context *ctxt)
2342 : : {
2343 : 285081 : return new pass_ipa_auto_profile (ctxt);
2344 : : }
|