1 /* Read and annotate call graph profile from the auto profile data file.
2 Copyright (C) 2014-2016 Free Software Foundation, Inc.
3 Contributed by Dehao Chen (dehao@google.com)
5 This file is part of GCC.
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
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
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/>. */
25 #include "coretypes.h"
30 #include "alloc-pool.h"
31 #include "tree-pass.h"
35 #include "diagnostic-core.h"
37 #include "langhooks.h"
40 #include "tree-cfgcleanup.h"
41 #include "tree-into-ssa.h"
42 #include "gimple-iterator.h"
43 #include "value-prof.h"
45 #include "symbol-summary.h"
47 #include "ipa-inline.h"
48 #include "tree-inline.h"
49 #include "auto-profile.h"
51 /* The following routines implements AutoFDO optimization.
53 This optimization uses sampling profiles to annotate basic block counts
54 and uses heuristics to estimate branch probabilities.
56 There are three phases in AutoFDO:
58 Phase 1: Read profile from the profile data file.
59 The following info is read from the profile datafile:
60 * string_table: a map between function name and its index.
61 * autofdo_source_profile: a map from function_instance name to
62 function_instance. This is represented as a forest of
64 * WorkingSet: a histogram of how many instructions are covered for a
65 given percentage of total cycles. This is describing the binary
66 level information (not source level). This info is used to help
67 decide if we want aggressive optimizations that could increase
68 code footprint (e.g. loop unroll etc.)
69 A function instance is an instance of function that could either be a
70 standalone symbol, or a clone of a function that is inlined into another
73 Phase 2: Early inline + value profile transformation.
74 Early inline uses autofdo_source_profile to find if a callsite is:
75 * inlined in the profiled binary.
76 * callee body is hot in the profiling run.
77 If both condition satisfies, early inline will inline the callsite
78 regardless of the code growth.
79 Phase 2 is an iterative process. During each iteration, we also check
80 if an indirect callsite is promoted and inlined in the profiling run.
81 If yes, vpt will happen to force promote it and in the next iteration,
82 einline will inline the promoted callsite in the next iteration.
84 Phase 3: Annotate control flow graph.
85 AutoFDO uses a separate pass to:
86 * Annotate basic block count
87 * Estimate branch probability
89 After the above 3 phases, all profile is readily annotated on the GCC IR.
90 AutoFDO tries to reuse all FDO infrastructure as much as possible to make
91 use of the profile. E.g. it uses existing mechanism to calculate the basic
92 block/edge frequency, as well as the cgraph node/edge count.
95 #define DEFAULT_AUTO_PROFILE_FILE "fbdata.afdo"
96 #define AUTO_PROFILE_VERSION 1
101 /* Represent a source location: (function_decl, lineno). */
102 typedef std::pair
<tree
, unsigned> decl_lineno
;
104 /* Represent an inline stack. vector[0] is the leaf node. */
105 typedef auto_vec
<decl_lineno
> inline_stack
;
107 /* String array that stores function names. */
108 typedef auto_vec
<char *> string_vector
;
110 /* Map from function name's index in string_table to target's
112 typedef std::map
<unsigned, gcov_type
> icall_target_map
;
114 /* Set of gimple stmts. Used to track if the stmt has already been promoted
116 typedef std::set
<gimple
*> stmt_set
;
118 /* Represent count info of an inline stack. */
121 /* Sampled count of the inline stack. */
124 /* Map from indirect call target to its sample count. */
125 icall_target_map targets
;
127 /* Whether this inline stack is already used in annotation.
129 Each inline stack should only be used to annotate IR once.
130 This will be enforced when instruction-level discriminator
135 /* operator< for "const char *". */
136 struct string_compare
138 bool operator()(const char *a
, const char *b
) const
140 return strcmp (a
, b
) < 0;
144 /* Store a string array, indexed by string position in the array. */
153 /* For a given string, returns its index. */
154 int get_index (const char *name
) const;
156 /* For a given decl, returns the index of the decl name. */
157 int get_index_by_decl (tree decl
) const;
159 /* For a given index, returns the string. */
160 const char *get_name (int index
) const;
162 /* Read profile, return TRUE on success. */
166 typedef std::map
<const char *, unsigned, string_compare
> string_index_map
;
167 string_vector vector_
;
168 string_index_map map_
;
171 /* Profile of a function instance:
172 1. total_count of the function.
173 2. head_count (entry basic block count) of the function (only valid when
174 function is a top-level function_instance, i.e. it is the original copy
175 instead of the inlined copy).
176 3. map from source location (decl_lineno) to profile (count_info).
177 4. map from callsite to callee function_instance. */
178 class function_instance
181 typedef auto_vec
<function_instance
*> function_instance_stack
;
183 /* Read the profile and return a function_instance with head count as
184 HEAD_COUNT. Recursively read callsites to create nested function_instances
185 too. STACK is used to track the recursive creation process. */
186 static function_instance
*
187 read_function_instance (function_instance_stack
*stack
,
188 gcov_type head_count
);
190 /* Recursively deallocate all callsites (nested function_instances). */
191 ~function_instance ();
210 /* Traverse callsites of the current function_instance to find one at the
211 location of LINENO and callee name represented in DECL. */
212 function_instance
*get_function_instance_by_decl (unsigned lineno
,
215 /* Store the profile info for LOC in INFO. Return TRUE if profile info
217 bool get_count_info (location_t loc
, count_info
*info
) const;
219 /* Read the inlined indirect call target profile for STMT and store it in
220 MAP, return the total count for all inlined indirect calls. */
221 gcov_type
find_icall_target_map (gcall
*stmt
, icall_target_map
*map
) const;
223 /* Sum of counts that is used during annotation. */
224 gcov_type
total_annotated_count () const;
226 /* Mark LOC as annotated. */
227 void mark_annotated (location_t loc
);
230 /* Callsite, represented as (decl_lineno, callee_function_name_index). */
231 typedef std::pair
<unsigned, unsigned> callsite
;
233 /* Map from callsite to callee function_instance. */
234 typedef std::map
<callsite
, function_instance
*> callsite_map
;
236 function_instance (unsigned name
, gcov_type head_count
)
237 : name_ (name
), total_count_ (0), head_count_ (head_count
)
241 /* Map from source location (decl_lineno) to profile (count_info). */
242 typedef std::map
<unsigned, count_info
> position_count_map
;
244 /* function_instance name index in the string_table. */
247 /* Total sample count. */
248 gcov_type total_count_
;
250 /* Entry BB's sample count. */
251 gcov_type head_count_
;
253 /* Map from callsite location to callee function_instance. */
254 callsite_map callsites
;
256 /* Map from source location to count_info. */
257 position_count_map pos_counts
;
260 /* Profile for all functions. */
261 class autofdo_source_profile
264 static autofdo_source_profile
*
267 autofdo_source_profile
*map
= new autofdo_source_profile ();
275 ~autofdo_source_profile ();
277 /* For a given DECL, returns the top-level function_instance. */
278 function_instance
*get_function_instance_by_decl (tree decl
) const;
280 /* Find count_info for a given gimple STMT. If found, store the count_info
281 in INFO and return true; otherwise return false. */
282 bool get_count_info (gimple
*stmt
, count_info
*info
) const;
284 /* Find total count of the callee of EDGE. */
285 gcov_type
get_callsite_total_count (struct cgraph_edge
*edge
) const;
287 /* Update value profile INFO for STMT from the inlined indirect callsite.
288 Return true if INFO is updated. */
289 bool update_inlined_ind_target (gcall
*stmt
, count_info
*info
);
291 /* Mark LOC as annotated. */
292 void mark_annotated (location_t loc
);
295 /* Map from function_instance name index (in string_table) to
296 function_instance. */
297 typedef std::map
<unsigned, function_instance
*> name_function_instance_map
;
299 autofdo_source_profile () {}
301 /* Read AutoFDO profile and returns TRUE on success. */
304 /* Return the function_instance in the profile that correspond to the
307 get_function_instance_by_inline_stack (const inline_stack
&stack
) const;
309 name_function_instance_map map_
;
312 /* Store the strings read from the profile data file. */
313 static string_table
*afdo_string_table
;
315 /* Store the AutoFDO source profile. */
316 static autofdo_source_profile
*afdo_source_profile
;
318 /* gcov_ctr_summary structure to store the profile_info. */
319 static struct gcov_ctr_summary
*afdo_profile_info
;
321 /* Helper functions. */
323 /* Return the original name of NAME: strip the suffix that starts
324 with '.' Caller is responsible for freeing RET. */
327 get_original_name (const char *name
)
329 char *ret
= xstrdup (name
);
330 char *find
= strchr (ret
, '.');
336 /* Return the combined location, which is a 32bit integer in which
337 higher 16 bits stores the line offset of LOC to the start lineno
338 of DECL, The lower 16 bits stores the discriminator. */
341 get_combined_location (location_t loc
, tree decl
)
343 /* TODO: allow more bits for line and less bits for discriminator. */
344 if (LOCATION_LINE (loc
) - DECL_SOURCE_LINE (decl
) >= (1<<16))
345 warning_at (loc
, OPT_Woverflow
, "Offset exceeds 16 bytes.");
346 return ((LOCATION_LINE (loc
) - DECL_SOURCE_LINE (decl
)) << 16);
349 /* Return the function decl of a given lexical BLOCK. */
352 get_function_decl_from_block (tree block
)
356 if (LOCATION_LOCUS (BLOCK_SOURCE_LOCATION (block
) == UNKNOWN_LOCATION
))
359 for (decl
= BLOCK_ABSTRACT_ORIGIN (block
);
360 decl
&& (TREE_CODE (decl
) == BLOCK
);
361 decl
= BLOCK_ABSTRACT_ORIGIN (decl
))
362 if (TREE_CODE (decl
) == FUNCTION_DECL
)
367 /* Store inline stack for STMT in STACK. */
370 get_inline_stack (location_t locus
, inline_stack
*stack
)
372 if (LOCATION_LOCUS (locus
) == UNKNOWN_LOCATION
)
375 tree block
= LOCATION_BLOCK (locus
);
376 if (block
&& TREE_CODE (block
) == BLOCK
)
379 for (block
= BLOCK_SUPERCONTEXT (block
);
380 block
&& (TREE_CODE (block
) == BLOCK
);
381 block
= BLOCK_SUPERCONTEXT (block
))
383 location_t tmp_locus
= BLOCK_SOURCE_LOCATION (block
);
384 if (LOCATION_LOCUS (tmp_locus
) == UNKNOWN_LOCATION
)
387 tree decl
= get_function_decl_from_block (block
);
389 std::make_pair (decl
, get_combined_location (locus
, decl
)));
395 std::make_pair (current_function_decl
,
396 get_combined_location (locus
, current_function_decl
)));
399 /* Return STMT's combined location, which is a 32bit integer in which
400 higher 16 bits stores the line offset of LOC to the start lineno
401 of DECL, The lower 16 bits stores the discriminator. */
404 get_relative_location_for_stmt (gimple
*stmt
)
406 location_t locus
= gimple_location (stmt
);
407 if (LOCATION_LOCUS (locus
) == UNKNOWN_LOCATION
)
408 return UNKNOWN_LOCATION
;
410 for (tree block
= gimple_block (stmt
); block
&& (TREE_CODE (block
) == BLOCK
);
411 block
= BLOCK_SUPERCONTEXT (block
))
412 if (LOCATION_LOCUS (BLOCK_SOURCE_LOCATION (block
)) != UNKNOWN_LOCATION
)
413 return get_combined_location (locus
,
414 get_function_decl_from_block (block
));
415 return get_combined_location (locus
, current_function_decl
);
418 /* Return true if BB contains indirect call. */
421 has_indirect_call (basic_block bb
)
423 gimple_stmt_iterator gsi
;
425 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
427 gimple
*stmt
= gsi_stmt (gsi
);
428 if (gimple_code (stmt
) == GIMPLE_CALL
&& !gimple_call_internal_p (stmt
)
429 && (gimple_call_fn (stmt
) == NULL
430 || TREE_CODE (gimple_call_fn (stmt
)) != FUNCTION_DECL
))
436 /* Member functions for string_table. */
440 string_table::~string_table ()
442 for (unsigned i
= 0; i
< vector_
.length (); i
++)
447 /* Return the index of a given function NAME. Return -1 if NAME is not
448 found in string table. */
451 string_table::get_index (const char *name
) const
455 string_index_map::const_iterator iter
= map_
.find (name
);
456 if (iter
== map_
.end ())
462 /* Return the index of a given function DECL. Return -1 if DECL is not
463 found in string table. */
466 string_table::get_index_by_decl (tree decl
) const
469 = get_original_name (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
)));
470 int ret
= get_index (name
);
474 ret
= get_index (lang_hooks
.dwarf_name (decl
, 0));
477 if (DECL_ABSTRACT_ORIGIN (decl
))
478 return get_index_by_decl (DECL_ABSTRACT_ORIGIN (decl
));
483 /* Return the function name of a given INDEX. */
486 string_table::get_name (int index
) const
488 gcc_assert (index
> 0 && index
< (int)vector_
.length ());
489 return vector_
[index
];
492 /* Read the string table. Return TRUE if reading is successful. */
495 string_table::read ()
497 if (gcov_read_unsigned () != GCOV_TAG_AFDO_FILE_NAMES
)
499 /* Skip the length of the section. */
500 gcov_read_unsigned ();
501 /* Read in the file name table. */
502 unsigned string_num
= gcov_read_unsigned ();
503 for (unsigned i
= 0; i
< string_num
; i
++)
505 vector_
.safe_push (get_original_name (gcov_read_string ()));
506 map_
[vector_
.last ()] = i
;
511 /* Member functions for function_instance. */
513 function_instance::~function_instance ()
515 for (callsite_map::iterator iter
= callsites
.begin ();
516 iter
!= callsites
.end (); ++iter
)
520 /* Traverse callsites of the current function_instance to find one at the
521 location of LINENO and callee name represented in DECL. */
524 function_instance::get_function_instance_by_decl (unsigned lineno
,
527 int func_name_idx
= afdo_string_table
->get_index_by_decl (decl
);
528 if (func_name_idx
!= -1)
530 callsite_map::const_iterator ret
531 = callsites
.find (std::make_pair (lineno
, func_name_idx
));
532 if (ret
!= callsites
.end ())
536 = afdo_string_table
->get_index (lang_hooks
.dwarf_name (decl
, 0));
537 if (func_name_idx
!= -1)
539 callsite_map::const_iterator ret
540 = callsites
.find (std::make_pair (lineno
, func_name_idx
));
541 if (ret
!= callsites
.end ())
544 if (DECL_ABSTRACT_ORIGIN (decl
))
545 return get_function_instance_by_decl (lineno
, DECL_ABSTRACT_ORIGIN (decl
));
550 /* Store the profile info for LOC in INFO. Return TRUE if profile info
554 function_instance::get_count_info (location_t loc
, count_info
*info
) const
556 position_count_map::const_iterator iter
= pos_counts
.find (loc
);
557 if (iter
== pos_counts
.end ())
559 *info
= iter
->second
;
563 /* Mark LOC as annotated. */
566 function_instance::mark_annotated (location_t loc
)
568 position_count_map::iterator iter
= pos_counts
.find (loc
);
569 if (iter
== pos_counts
.end ())
571 iter
->second
.annotated
= true;
574 /* Read the inlined indirect call target profile for STMT and store it in
575 MAP, return the total count for all inlined indirect calls. */
578 function_instance::find_icall_target_map (gcall
*stmt
,
579 icall_target_map
*map
) const
582 unsigned stmt_offset
= get_relative_location_for_stmt (stmt
);
584 for (callsite_map::const_iterator iter
= callsites
.begin ();
585 iter
!= callsites
.end (); ++iter
)
587 unsigned callee
= iter
->second
->name ();
588 /* Check if callsite location match the stmt. */
589 if (iter
->first
.first
!= stmt_offset
)
591 struct cgraph_node
*node
= cgraph_node::get_for_asmname (
592 get_identifier (afdo_string_table
->get_name (callee
)));
595 if (!check_ic_target (stmt
, node
))
597 (*map
)[callee
] = iter
->second
->total_count ();
598 ret
+= iter
->second
->total_count ();
603 /* Read the profile and create a function_instance with head count as
604 HEAD_COUNT. Recursively read callsites to create nested function_instances
605 too. STACK is used to track the recursive creation process. */
607 /* function instance profile format:
611 NUM_POS_COUNTS: 4 bytes
612 NUM_CALLSITES: 4 byte
614 POS_1_OFFSET: 4 bytes
618 VALUE_PROFILE_TYPE: 4 bytes
628 CALLSITE_1_OFFSET: 4 bytes
629 FUNCTION_INSTANCE_PROFILE (nested)
635 function_instance::read_function_instance (function_instance_stack
*stack
,
636 gcov_type head_count
)
638 unsigned name
= gcov_read_unsigned ();
639 unsigned num_pos_counts
= gcov_read_unsigned ();
640 unsigned num_callsites
= gcov_read_unsigned ();
641 function_instance
*s
= new function_instance (name
, head_count
);
642 stack
->safe_push (s
);
644 for (unsigned i
= 0; i
< num_pos_counts
; i
++)
646 unsigned offset
= gcov_read_unsigned () & 0xffff0000;
647 unsigned num_targets
= gcov_read_unsigned ();
648 gcov_type count
= gcov_read_counter ();
649 s
->pos_counts
[offset
].count
= count
;
650 for (unsigned j
= 0; j
< stack
->length (); j
++)
651 (*stack
)[j
]->total_count_
+= count
;
652 for (unsigned j
= 0; j
< num_targets
; j
++)
654 /* Only indirect call target histogram is supported now. */
655 gcov_read_unsigned ();
656 gcov_type target_idx
= gcov_read_counter ();
657 s
->pos_counts
[offset
].targets
[target_idx
] = gcov_read_counter ();
660 for (unsigned i
= 0; i
< num_callsites
; i
++)
662 unsigned offset
= gcov_read_unsigned ();
663 function_instance
*callee_function_instance
664 = read_function_instance (stack
, 0);
665 s
->callsites
[std::make_pair (offset
, callee_function_instance
->name ())]
666 = callee_function_instance
;
672 /* Sum of counts that is used during annotation. */
675 function_instance::total_annotated_count () const
678 for (callsite_map::const_iterator iter
= callsites
.begin ();
679 iter
!= callsites
.end (); ++iter
)
680 ret
+= iter
->second
->total_annotated_count ();
681 for (position_count_map::const_iterator iter
= pos_counts
.begin ();
682 iter
!= pos_counts
.end (); ++iter
)
683 if (iter
->second
.annotated
)
684 ret
+= iter
->second
.count
;
688 /* Member functions for autofdo_source_profile. */
690 autofdo_source_profile::~autofdo_source_profile ()
692 for (name_function_instance_map::const_iterator iter
= map_
.begin ();
693 iter
!= map_
.end (); ++iter
)
697 /* For a given DECL, returns the top-level function_instance. */
700 autofdo_source_profile::get_function_instance_by_decl (tree decl
) const
702 int index
= afdo_string_table
->get_index_by_decl (decl
);
705 name_function_instance_map::const_iterator ret
= map_
.find (index
);
706 return ret
== map_
.end () ? NULL
: ret
->second
;
709 /* Find count_info for a given gimple STMT. If found, store the count_info
710 in INFO and return true; otherwise return false. */
713 autofdo_source_profile::get_count_info (gimple
*stmt
, count_info
*info
) const
715 if (LOCATION_LOCUS (gimple_location (stmt
)) == cfun
->function_end_locus
)
719 get_inline_stack (gimple_location (stmt
), &stack
);
720 if (stack
.length () == 0)
722 function_instance
*s
= get_function_instance_by_inline_stack (stack
);
725 return s
->get_count_info (stack
[0].second
, info
);
728 /* Mark LOC as annotated. */
731 autofdo_source_profile::mark_annotated (location_t loc
)
734 get_inline_stack (loc
, &stack
);
735 if (stack
.length () == 0)
737 function_instance
*s
= get_function_instance_by_inline_stack (stack
);
740 s
->mark_annotated (stack
[0].second
);
743 /* Update value profile INFO for STMT from the inlined indirect callsite.
744 Return true if INFO is updated. */
747 autofdo_source_profile::update_inlined_ind_target (gcall
*stmt
,
750 if (LOCATION_LOCUS (gimple_location (stmt
)) == cfun
->function_end_locus
)
754 get_count_info (stmt
, &old_info
);
756 for (icall_target_map::const_iterator iter
= old_info
.targets
.begin ();
757 iter
!= old_info
.targets
.end (); ++iter
)
758 total
+= iter
->second
;
760 /* Program behavior changed, original promoted (and inlined) target is not
761 hot any more. Will avoid promote the original target.
763 To check if original promoted target is still hot, we check the total
764 count of the unpromoted targets (stored in old_info). If it is no less
765 than half of the callsite count (stored in INFO), the original promoted
766 target is considered not hot any more. */
767 if (total
>= info
->count
/ 2)
771 get_inline_stack (gimple_location (stmt
), &stack
);
772 if (stack
.length () == 0)
774 function_instance
*s
= get_function_instance_by_inline_stack (stack
);
777 icall_target_map map
;
778 if (s
->find_icall_target_map (stmt
, &map
) == 0)
780 for (icall_target_map::const_iterator iter
= map
.begin ();
781 iter
!= map
.end (); ++iter
)
782 info
->targets
[iter
->first
] = iter
->second
;
786 /* Find total count of the callee of EDGE. */
789 autofdo_source_profile::get_callsite_total_count (
790 struct cgraph_edge
*edge
) const
793 stack
.safe_push (std::make_pair (edge
->callee
->decl
, 0));
794 get_inline_stack (gimple_location (edge
->call_stmt
), &stack
);
796 function_instance
*s
= get_function_instance_by_inline_stack (stack
);
798 || afdo_string_table
->get_index (IDENTIFIER_POINTER (
799 DECL_ASSEMBLER_NAME (edge
->callee
->decl
))) != s
->name ())
802 return s
->total_count ();
805 /* Read AutoFDO profile and returns TRUE on success. */
807 /* source profile format:
809 GCOV_TAG_AFDO_FUNCTION: 4 bytes
811 NUM_FUNCTIONS: 4 bytes
815 FUNCTION_INSTANCE_N. */
818 autofdo_source_profile::read ()
820 if (gcov_read_unsigned () != GCOV_TAG_AFDO_FUNCTION
)
822 inform (0, "Not expected TAG.");
826 /* Skip the length of the section. */
827 gcov_read_unsigned ();
829 /* Read in the function/callsite profile, and store it in local
831 unsigned function_num
= gcov_read_unsigned ();
832 for (unsigned i
= 0; i
< function_num
; i
++)
834 function_instance::function_instance_stack stack
;
835 function_instance
*s
= function_instance::read_function_instance (
836 &stack
, gcov_read_counter ());
837 afdo_profile_info
->sum_all
+= s
->total_count ();
838 map_
[s
->name ()] = s
;
843 /* Return the function_instance in the profile that correspond to the
847 autofdo_source_profile::get_function_instance_by_inline_stack (
848 const inline_stack
&stack
) const
850 name_function_instance_map::const_iterator iter
= map_
.find (
851 afdo_string_table
->get_index_by_decl (stack
[stack
.length () - 1].first
));
852 if (iter
== map_
.end())
854 function_instance
*s
= iter
->second
;
855 for (unsigned i
= stack
.length() - 1; i
> 0; i
--)
857 s
= s
->get_function_instance_by_decl (
858 stack
[i
].second
, stack
[i
- 1].first
);
865 /* Module profile is only used by LIPO. Here we simply ignore it. */
868 fake_read_autofdo_module_profile ()
870 /* Read in the module info. */
871 gcov_read_unsigned ();
873 /* Skip the length of the section. */
874 gcov_read_unsigned ();
876 /* Read in the file name table. */
877 unsigned total_module_num
= gcov_read_unsigned ();
878 gcc_assert (total_module_num
== 0);
881 /* Read data from profile data file. */
886 if (gcov_open (auto_profile_file
, 1) == 0)
888 error ("Cannot open profile file %s.", auto_profile_file
);
892 if (gcov_read_unsigned () != GCOV_DATA_MAGIC
)
894 error ("AutoFDO profile magic number does not match.");
898 /* Skip the version number. */
899 unsigned version
= gcov_read_unsigned ();
900 if (version
!= AUTO_PROFILE_VERSION
)
902 error ("AutoFDO profile version %u does match %u.",
903 version
, AUTO_PROFILE_VERSION
);
907 /* Skip the empty integer. */
908 gcov_read_unsigned ();
911 afdo_string_table
= new string_table ();
912 if (!afdo_string_table
->read())
914 error ("Cannot read string table from %s.", auto_profile_file
);
918 /* autofdo_source_profile. */
919 afdo_source_profile
= autofdo_source_profile::create ();
920 if (afdo_source_profile
== NULL
)
922 error ("Cannot read function profile from %s.", auto_profile_file
);
926 /* autofdo_module_profile. */
927 fake_read_autofdo_module_profile ();
929 /* Read in the working set. */
930 if (gcov_read_unsigned () != GCOV_TAG_AFDO_WORKING_SET
)
932 error ("Cannot read working set from %s.", auto_profile_file
);
936 /* Skip the length of the section. */
937 gcov_read_unsigned ();
938 gcov_working_set_t set
[128];
939 for (unsigned i
= 0; i
< 128; i
++)
941 set
[i
].num_counters
= gcov_read_unsigned ();
942 set
[i
].min_counter
= gcov_read_counter ();
944 add_working_set (set
);
947 /* From AutoFDO profiles, find values inside STMT for that we want to measure
948 histograms for indirect-call optimization.
950 This function is actually served for 2 purposes:
951 * before annotation, we need to mark histogram, promote and inline
952 * after annotation, we just need to mark, and let follow-up logic to
953 decide if it needs to promote and inline. */
956 afdo_indirect_call (gimple_stmt_iterator
*gsi
, const icall_target_map
&map
,
959 gimple
*gs
= gsi_stmt (*gsi
);
962 if (map
.size () == 0)
964 gcall
*stmt
= dyn_cast
<gcall
*> (gs
);
965 if ((!stmt
) || gimple_call_fndecl (stmt
) != NULL_TREE
)
968 callee
= gimple_call_fn (stmt
);
970 histogram_value hist
= gimple_alloc_histogram_value (
971 cfun
, HIST_TYPE_INDIR_CALL
, stmt
, callee
);
972 hist
->n_counters
= 3;
973 hist
->hvalue
.counters
= XNEWVEC (gcov_type
, hist
->n_counters
);
974 gimple_add_histogram_value (cfun
, stmt
, hist
);
977 icall_target_map::const_iterator max_iter
= map
.end ();
979 for (icall_target_map::const_iterator iter
= map
.begin ();
980 iter
!= map
.end (); ++iter
)
982 total
+= iter
->second
;
983 if (max_iter
== map
.end () || max_iter
->second
< iter
->second
)
987 hist
->hvalue
.counters
[0]
988 = (unsigned long long)afdo_string_table
->get_name (max_iter
->first
);
989 hist
->hvalue
.counters
[1] = max_iter
->second
;
990 hist
->hvalue
.counters
[2] = total
;
995 struct cgraph_edge
*indirect_edge
996 = cgraph_node::get (current_function_decl
)->get_edge (stmt
);
997 struct cgraph_node
*direct_call
= cgraph_node::get_for_asmname (
998 get_identifier ((const char *) hist
->hvalue
.counters
[0]));
1000 if (direct_call
== NULL
|| !check_ic_target (stmt
, direct_call
))
1002 if (DECL_STRUCT_FUNCTION (direct_call
->decl
) == NULL
)
1004 struct cgraph_edge
*new_edge
1005 = indirect_edge
->make_speculative (direct_call
, 0, 0);
1006 new_edge
->redirect_call_stmt_to_callee ();
1007 gimple_remove_histogram_value (cfun
, stmt
, hist
);
1008 inline_call (new_edge
, true, NULL
, NULL
, false);
1011 /* From AutoFDO profiles, find values inside STMT for that we want to measure
1012 histograms and adds them to list VALUES. */
1015 afdo_vpt (gimple_stmt_iterator
*gsi
, const icall_target_map
&map
,
1018 afdo_indirect_call (gsi
, map
, transform
);
1021 typedef std::set
<basic_block
> bb_set
;
1022 typedef std::set
<edge
> edge_set
;
1025 is_bb_annotated (const basic_block bb
, const bb_set
&annotated
)
1027 return annotated
.find (bb
) != annotated
.end ();
1031 set_bb_annotated (basic_block bb
, bb_set
*annotated
)
1033 annotated
->insert (bb
);
1037 is_edge_annotated (const edge e
, const edge_set
&annotated
)
1039 return annotated
.find (e
) != annotated
.end ();
1043 set_edge_annotated (edge e
, edge_set
*annotated
)
1045 annotated
->insert (e
);
1048 /* For a given BB, set its execution count. Attach value profile if a stmt
1049 is not in PROMOTED, because we only want to promote an indirect call once.
1050 Return TRUE if BB is annotated. */
1053 afdo_set_bb_count (basic_block bb
, const stmt_set
&promoted
)
1055 gimple_stmt_iterator gsi
;
1058 gcov_type max_count
= 0;
1059 bool has_annotated
= false;
1061 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
1064 gimple
*stmt
= gsi_stmt (gsi
);
1065 if (gimple_clobber_p (stmt
) || is_gimple_debug (stmt
))
1067 if (afdo_source_profile
->get_count_info (stmt
, &info
))
1069 if (info
.count
> max_count
)
1070 max_count
= info
.count
;
1071 has_annotated
= true;
1072 if (info
.targets
.size () > 0
1073 && promoted
.find (stmt
) == promoted
.end ())
1074 afdo_vpt (&gsi
, info
.targets
, false);
1081 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
1082 afdo_source_profile
->mark_annotated (gimple_location (gsi_stmt (gsi
)));
1083 for (gphi_iterator gpi
= gsi_start_phis (bb
);
1087 gphi
*phi
= gpi
.phi ();
1089 for (i
= 0; i
< gimple_phi_num_args (phi
); i
++)
1090 afdo_source_profile
->mark_annotated (gimple_phi_arg_location (phi
, i
));
1092 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1093 afdo_source_profile
->mark_annotated (e
->goto_locus
);
1095 bb
->count
= max_count
;
1099 /* BB1 and BB2 are in an equivalent class iff:
1100 1. BB1 dominates BB2.
1101 2. BB2 post-dominates BB1.
1102 3. BB1 and BB2 are in the same loop nest.
1103 This function finds the equivalent class for each basic block, and
1104 stores a pointer to the first BB in its equivalent class. Meanwhile,
1105 set bb counts for the same equivalent class to be idenical. Update
1106 ANNOTATED_BB for the first BB in its equivalent class. */
1109 afdo_find_equiv_class (bb_set
*annotated_bb
)
1113 FOR_ALL_BB_FN (bb
, cfun
)
1116 FOR_ALL_BB_FN (bb
, cfun
)
1118 vec
<basic_block
> dom_bbs
;
1122 if (bb
->aux
!= NULL
)
1125 dom_bbs
= get_dominated_by (CDI_DOMINATORS
, bb
);
1126 FOR_EACH_VEC_ELT (dom_bbs
, i
, bb1
)
1127 if (bb1
->aux
== NULL
&& dominated_by_p (CDI_POST_DOMINATORS
, bb
, bb1
)
1128 && bb1
->loop_father
== bb
->loop_father
)
1131 if (bb1
->count
> bb
->count
&& is_bb_annotated (bb1
, *annotated_bb
))
1133 bb
->count
= bb1
->count
;
1134 set_bb_annotated (bb
, annotated_bb
);
1137 dom_bbs
= get_dominated_by (CDI_POST_DOMINATORS
, bb
);
1138 FOR_EACH_VEC_ELT (dom_bbs
, i
, bb1
)
1139 if (bb1
->aux
== NULL
&& dominated_by_p (CDI_DOMINATORS
, bb
, bb1
)
1140 && bb1
->loop_father
== bb
->loop_father
)
1143 if (bb1
->count
> bb
->count
&& is_bb_annotated (bb1
, *annotated_bb
))
1145 bb
->count
= bb1
->count
;
1146 set_bb_annotated (bb
, annotated_bb
);
1152 /* If a basic block's count is known, and only one of its in/out edges' count
1153 is unknown, its count can be calculated. Meanwhile, if all of the in/out
1154 edges' counts are known, then the basic block's unknown count can also be
1156 IS_SUCC is true if out edges of a basic blocks are examined.
1157 Update ANNOTATED_BB and ANNOTATED_EDGE accordingly.
1158 Return TRUE if any basic block/edge count is changed. */
1161 afdo_propagate_edge (bool is_succ
, bb_set
*annotated_bb
,
1162 edge_set
*annotated_edge
)
1165 bool changed
= false;
1167 FOR_EACH_BB_FN (bb
, cfun
)
1169 edge e
, unknown_edge
= NULL
;
1171 int num_unknown_edge
= 0;
1172 gcov_type total_known_count
= 0;
1174 FOR_EACH_EDGE (e
, ei
, is_succ
? bb
->succs
: bb
->preds
)
1175 if (!is_edge_annotated (e
, *annotated_edge
))
1176 num_unknown_edge
++, unknown_edge
= e
;
1178 total_known_count
+= e
->count
;
1180 if (num_unknown_edge
== 0)
1182 if (total_known_count
> bb
->count
)
1184 bb
->count
= total_known_count
;
1187 if (!is_bb_annotated (bb
, *annotated_bb
))
1189 set_bb_annotated (bb
, annotated_bb
);
1193 else if (num_unknown_edge
== 1 && is_bb_annotated (bb
, *annotated_bb
))
1195 if (bb
->count
>= total_known_count
)
1196 unknown_edge
->count
= bb
->count
- total_known_count
;
1198 unknown_edge
->count
= 0;
1199 set_edge_annotated (unknown_edge
, annotated_edge
);
1206 /* Special propagation for circuit expressions. Because GCC translates
1207 control flow into data flow for circuit expressions. E.g.
1214 will be translated into:
1229 tmp = PHI (0 (BB1), 0 (BB.t1), 1 (BB.t2)
1235 In this case, we need to propagate through PHI to determine the edge
1236 count of BB1->BB.t1, BB.t1->BB.t2.
1237 Update ANNOTATED_EDGE accordingly. */
1240 afdo_propagate_circuit (const bb_set
&annotated_bb
, edge_set
*annotated_edge
)
1243 FOR_ALL_BB_FN (bb
, cfun
)
1246 tree cmp_rhs
, cmp_lhs
;
1247 gimple
*cmp_stmt
= last_stmt (bb
);
1251 if (!cmp_stmt
|| gimple_code (cmp_stmt
) != GIMPLE_COND
)
1253 cmp_rhs
= gimple_cond_rhs (cmp_stmt
);
1254 cmp_lhs
= gimple_cond_lhs (cmp_stmt
);
1255 if (!TREE_CONSTANT (cmp_rhs
)
1256 || !(integer_zerop (cmp_rhs
) || integer_onep (cmp_rhs
)))
1258 if (TREE_CODE (cmp_lhs
) != SSA_NAME
)
1260 if (!is_bb_annotated (bb
, annotated_bb
))
1262 def_stmt
= SSA_NAME_DEF_STMT (cmp_lhs
);
1263 while (def_stmt
&& gimple_code (def_stmt
) == GIMPLE_ASSIGN
1264 && gimple_assign_single_p (def_stmt
)
1265 && TREE_CODE (gimple_assign_rhs1 (def_stmt
)) == SSA_NAME
)
1266 def_stmt
= SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def_stmt
));
1269 gphi
*phi_stmt
= dyn_cast
<gphi
*> (def_stmt
);
1272 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1274 unsigned i
, total
= 0;
1276 bool check_value_one
= (((integer_onep (cmp_rhs
))
1277 ^ (gimple_cond_code (cmp_stmt
) == EQ_EXPR
))
1278 ^ ((e
->flags
& EDGE_TRUE_VALUE
) != 0));
1279 if (!is_edge_annotated (e
, *annotated_edge
))
1281 for (i
= 0; i
< gimple_phi_num_args (phi_stmt
); i
++)
1283 tree val
= gimple_phi_arg_def (phi_stmt
, i
);
1284 edge ep
= gimple_phi_arg_edge (phi_stmt
, i
);
1286 if (!TREE_CONSTANT (val
)
1287 || !(integer_zerop (val
) || integer_onep (val
)))
1289 if (check_value_one
^ integer_onep (val
))
1293 if (e
->probability
== 0 && !is_edge_annotated (ep
, *annotated_edge
))
1295 ep
->probability
= 0;
1297 set_edge_annotated (ep
, annotated_edge
);
1300 if (total
== 1 && !is_edge_annotated (only_one
, *annotated_edge
))
1302 only_one
->probability
= e
->probability
;
1303 only_one
->count
= e
->count
;
1304 set_edge_annotated (only_one
, annotated_edge
);
1310 /* Propagate the basic block count and edge count on the control flow
1311 graph. We do the propagation iteratively until stablize. */
1314 afdo_propagate (bb_set
*annotated_bb
, edge_set
*annotated_edge
)
1317 bool changed
= true;
1320 FOR_ALL_BB_FN (bb
, cfun
)
1322 bb
->count
= ((basic_block
)bb
->aux
)->count
;
1323 if (is_bb_annotated ((const basic_block
)bb
->aux
, *annotated_bb
))
1324 set_bb_annotated (bb
, annotated_bb
);
1327 while (changed
&& i
++ < 10)
1331 if (afdo_propagate_edge (true, annotated_bb
, annotated_edge
))
1333 if (afdo_propagate_edge (false, annotated_bb
, annotated_edge
))
1335 afdo_propagate_circuit (*annotated_bb
, annotated_edge
);
1339 /* Propagate counts on control flow graph and calculate branch
1343 afdo_calculate_branch_prob (bb_set
*annotated_bb
, edge_set
*annotated_edge
)
1346 bool has_sample
= false;
1348 FOR_EACH_BB_FN (bb
, cfun
)
1360 calculate_dominance_info (CDI_POST_DOMINATORS
);
1361 calculate_dominance_info (CDI_DOMINATORS
);
1362 loop_optimizer_init (0);
1364 afdo_find_equiv_class (annotated_bb
);
1365 afdo_propagate (annotated_bb
, annotated_edge
);
1367 FOR_EACH_BB_FN (bb
, cfun
)
1371 int num_unknown_succ
= 0;
1372 gcov_type total_count
= 0;
1374 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1376 if (!is_edge_annotated (e
, *annotated_edge
))
1379 total_count
+= e
->count
;
1381 if (num_unknown_succ
== 0 && total_count
> 0)
1383 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1384 e
->probability
= (double)e
->count
* REG_BR_PROB_BASE
/ total_count
;
1387 FOR_ALL_BB_FN (bb
, cfun
)
1392 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1393 e
->count
= (double)bb
->count
* e
->probability
/ REG_BR_PROB_BASE
;
1397 loop_optimizer_finalize ();
1398 free_dominance_info (CDI_DOMINATORS
);
1399 free_dominance_info (CDI_POST_DOMINATORS
);
1402 /* Perform value profile transformation using AutoFDO profile. Add the
1403 promoted stmts to PROMOTED_STMTS. Return TRUE if there is any
1404 indirect call promoted. */
1407 afdo_vpt_for_early_inline (stmt_set
*promoted_stmts
)
1410 if (afdo_source_profile
->get_function_instance_by_decl (
1411 current_function_decl
) == NULL
)
1414 compute_inline_parameters (cgraph_node::get (current_function_decl
), true);
1416 bool has_vpt
= false;
1417 FOR_EACH_BB_FN (bb
, cfun
)
1419 if (!has_indirect_call (bb
))
1421 gimple_stmt_iterator gsi
;
1423 gcov_type bb_count
= 0;
1424 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
1427 gimple
*stmt
= gsi_stmt (gsi
);
1428 if (afdo_source_profile
->get_count_info (stmt
, &info
))
1429 bb_count
= MAX (bb_count
, info
.count
);
1432 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
1434 gcall
*stmt
= dyn_cast
<gcall
*> (gsi_stmt (gsi
));
1435 /* IC_promotion and early_inline_2 is done in multiple iterations.
1436 No need to promoted the stmt if its in promoted_stmts (means
1437 it is already been promoted in the previous iterations). */
1438 if ((!stmt
) || gimple_call_fn (stmt
) == NULL
1439 || TREE_CODE (gimple_call_fn (stmt
)) == FUNCTION_DECL
1440 || promoted_stmts
->find (stmt
) != promoted_stmts
->end ())
1444 afdo_source_profile
->get_count_info (stmt
, &info
);
1445 info
.count
= bb_count
;
1446 if (afdo_source_profile
->update_inlined_ind_target (stmt
, &info
))
1448 /* Promote the indirect call and update the promoted_stmts. */
1449 promoted_stmts
->insert (stmt
);
1450 afdo_vpt (&gsi
, info
.targets
, true);
1458 optimize_inline_calls (current_function_decl
);
1465 /* Annotate auto profile to the control flow graph. Do not annotate value
1466 profile for stmts in PROMOTED_STMTS. */
1469 afdo_annotate_cfg (const stmt_set
&promoted_stmts
)
1472 bb_set annotated_bb
;
1473 edge_set annotated_edge
;
1474 const function_instance
*s
1475 = afdo_source_profile
->get_function_instance_by_decl (
1476 current_function_decl
);
1480 cgraph_node::get (current_function_decl
)->count
= s
->head_count ();
1481 ENTRY_BLOCK_PTR_FOR_FN (cfun
)->count
= s
->head_count ();
1482 gcov_type max_count
= ENTRY_BLOCK_PTR_FOR_FN (cfun
)->count
;
1484 FOR_EACH_BB_FN (bb
, cfun
)
1490 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1493 if (afdo_set_bb_count (bb
, promoted_stmts
))
1494 set_bb_annotated (bb
, &annotated_bb
);
1495 if (bb
->count
> max_count
)
1496 max_count
= bb
->count
;
1498 if (ENTRY_BLOCK_PTR_FOR_FN (cfun
)->count
1499 > ENTRY_BLOCK_PTR_FOR_FN (cfun
)->next_bb
->count
)
1501 ENTRY_BLOCK_PTR_FOR_FN (cfun
)->next_bb
->count
1502 = ENTRY_BLOCK_PTR_FOR_FN (cfun
)->count
;
1503 set_bb_annotated (ENTRY_BLOCK_PTR_FOR_FN (cfun
)->next_bb
, &annotated_bb
);
1505 if (ENTRY_BLOCK_PTR_FOR_FN (cfun
)->count
1506 > EXIT_BLOCK_PTR_FOR_FN (cfun
)->prev_bb
->count
)
1508 EXIT_BLOCK_PTR_FOR_FN (cfun
)->prev_bb
->count
1509 = ENTRY_BLOCK_PTR_FOR_FN (cfun
)->count
;
1510 set_bb_annotated (EXIT_BLOCK_PTR_FOR_FN (cfun
)->prev_bb
, &annotated_bb
);
1512 afdo_source_profile
->mark_annotated (
1513 DECL_SOURCE_LOCATION (current_function_decl
));
1514 afdo_source_profile
->mark_annotated (cfun
->function_start_locus
);
1515 afdo_source_profile
->mark_annotated (cfun
->function_end_locus
);
1518 afdo_calculate_branch_prob (&annotated_bb
, &annotated_edge
);
1520 profile_status_for_fn (cfun
) = PROFILE_READ
;
1522 if (flag_value_profile_transformations
)
1524 gimple_value_profile_transformations ();
1525 free_dominance_info (CDI_DOMINATORS
);
1526 free_dominance_info (CDI_POST_DOMINATORS
);
1527 update_ssa (TODO_update_ssa
);
1531 /* Wrapper function to invoke early inliner. */
1536 compute_inline_parameters (cgraph_node::get (current_function_decl
), true);
1537 unsigned todo
= early_inliner (cfun
);
1538 if (todo
& TODO_update_ssa_any
)
1539 update_ssa (TODO_update_ssa
);
1542 /* Use AutoFDO profile to annoate the control flow graph.
1543 Return the todo flag. */
1548 struct cgraph_node
*node
;
1550 if (symtab
->state
== FINISHED
)
1553 init_node_map (true);
1554 profile_info
= autofdo::afdo_profile_info
;
1556 FOR_EACH_FUNCTION (node
)
1558 if (!gimple_has_body_p (node
->decl
))
1561 /* Don't profile functions produced for builtin stuff. */
1562 if (DECL_SOURCE_LOCATION (node
->decl
) == BUILTINS_LOCATION
)
1565 push_cfun (DECL_STRUCT_FUNCTION (node
->decl
));
1567 /* First do indirect call promotion and early inline to make the
1568 IR match the profiled binary before actual annotation.
1570 This is needed because an indirect call might have been promoted
1571 and inlined in the profiled binary. If we do not promote and
1572 inline these indirect calls before annotation, the profile for
1573 these promoted functions will be lost.
1575 e.g. foo() --indirect_call--> bar()
1576 In profiled binary, the callsite is promoted and inlined, making
1577 the profile look like:
1587 Before AutoFDO pass, loc_foo_2 is not promoted thus not inlined.
1588 If we perform annotation on it, the profile inside bar@loc_foo2
1591 To avoid this, we promote loc_foo_2 and inline the promoted bar
1592 function before annotation, so the profile inside bar@loc_foo2
1594 autofdo::stmt_set promoted_stmts
;
1595 for (int i
= 0; i
< PARAM_VALUE (PARAM_EARLY_INLINER_MAX_ITERATIONS
); i
++)
1597 if (!flag_value_profile_transformations
1598 || !autofdo::afdo_vpt_for_early_inline (&promoted_stmts
))
1604 autofdo::afdo_annotate_cfg (promoted_stmts
);
1605 compute_function_frequency ();
1607 /* Local pure-const may imply need to fixup the cfg. */
1608 if (execute_fixup_cfg () & TODO_cleanup_cfg
)
1609 cleanup_tree_cfg ();
1611 free_dominance_info (CDI_DOMINATORS
);
1612 free_dominance_info (CDI_POST_DOMINATORS
);
1613 cgraph_edge::rebuild_edges ();
1614 compute_inline_parameters (cgraph_node::get (current_function_decl
), true);
1618 return TODO_rebuild_cgraph_edges
;
1620 } /* namespace autofdo. */
1622 /* Read the profile from the profile data file. */
1625 read_autofdo_file (void)
1627 if (auto_profile_file
== NULL
)
1628 auto_profile_file
= DEFAULT_AUTO_PROFILE_FILE
;
1630 autofdo::afdo_profile_info
= (struct gcov_ctr_summary
*)xcalloc (
1631 1, sizeof (struct gcov_ctr_summary
));
1632 autofdo::afdo_profile_info
->runs
= 1;
1633 autofdo::afdo_profile_info
->sum_max
= 0;
1634 autofdo::afdo_profile_info
->sum_all
= 0;
1636 /* Read the profile from the profile file. */
1637 autofdo::read_profile ();
1640 /* Free the resources. */
1643 end_auto_profile (void)
1645 delete autofdo::afdo_source_profile
;
1646 delete autofdo::afdo_string_table
;
1647 profile_info
= NULL
;
1650 /* Returns TRUE if EDGE is hot enough to be inlined early. */
1653 afdo_callsite_hot_enough_for_early_inline (struct cgraph_edge
*edge
)
1656 = autofdo::afdo_source_profile
->get_callsite_total_count (edge
);
1661 const struct gcov_ctr_summary
*saved_profile_info
= profile_info
;
1662 /* At early inline stage, profile_info is not set yet. We need to
1663 temporarily set it to afdo_profile_info to calculate hotness. */
1664 profile_info
= autofdo::afdo_profile_info
;
1665 is_hot
= maybe_hot_count_p (NULL
, count
);
1666 profile_info
= saved_profile_info
;
1676 const pass_data pass_data_ipa_auto_profile
= {
1677 SIMPLE_IPA_PASS
, "afdo", /* name */
1678 OPTGROUP_NONE
, /* optinfo_flags */
1679 TV_IPA_AUTOFDO
, /* tv_id */
1680 0, /* properties_required */
1681 0, /* properties_provided */
1682 0, /* properties_destroyed */
1683 0, /* todo_flags_start */
1684 0, /* todo_flags_finish */
1687 class pass_ipa_auto_profile
: public simple_ipa_opt_pass
1690 pass_ipa_auto_profile (gcc::context
*ctxt
)
1691 : simple_ipa_opt_pass (pass_data_ipa_auto_profile
, ctxt
)
1695 /* opt_pass methods: */
1699 return flag_auto_profile
;
1701 virtual unsigned int
1702 execute (function
*)
1704 return autofdo::auto_profile ();
1706 }; // class pass_ipa_auto_profile
1710 simple_ipa_opt_pass
*
1711 make_pass_ipa_auto_profile (gcc::context
*ctxt
)
1713 return new pass_ipa_auto_profile (ctxt
);