1 /* Read and annotate call graph profile from the auto profile data file.
2 Copyright (C) 2014. 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/>. */
28 #include "coretypes.h"
30 #include "tree-pass.h"
32 #include "basic-block.h"
33 #include "diagnostic-core.h"
37 #include "langhooks.h"
39 #include "tree-pass.h"
41 #include "tree-ssa-alias.h"
43 #include "tree-cfgcleanup.h"
44 #include "tree-ssa-operands.h"
45 #include "tree-into-ssa.h"
46 #include "internal-fn.h"
48 #include "gimple-expr.h"
50 #include "gimple-iterator.h"
51 #include "gimple-ssa.h"
53 #include "value-prof.h"
56 #include "ipa-inline.h"
57 #include "tree-inline.h"
58 #include "stringpool.h"
59 #include "auto-profile.h"
62 /* The following routines implements AutoFDO optimization.
64 This optimization uses sampling profiles to annotate basic block counts
65 and uses heuristics to estimate branch probabilities.
67 There are three phases in AutoFDO:
69 Phase 1: Read profile from the profile data file.
70 The following info is read from the profile datafile:
71 * string_table: a map between function name and its index.
72 * autofdo_source_profile: a map from function_instance name to
73 function_instance. This is represented as a forest of
75 * WorkingSet: a histogram of how many instructions are covered for a
76 given percentage of total cycles. This is describing the binary
77 level information (not source level). This info is used to help
78 decide if we want aggressive optimizations that could increase
79 code footprint (e.g. loop unroll etc.)
80 A function instance is an instance of function that could either be a
81 standalone symbol, or a clone of a function that is inlined into another
84 Phase 2: Early inline + valur profile transformation.
85 Early inline uses autofdo_source_profile to find if a callsite is:
86 * inlined in the profiled binary.
87 * callee body is hot in the profiling run.
88 If both condition satisfies, early inline will inline the callsite
89 regardless of the code growth.
90 Phase 2 is an iterative process. During each iteration, we also check
91 if an indirect callsite is promoted and inlined in the profiling run.
92 If yes, vpt will happen to force promote it and in the next iteration,
93 einline will inline the promoted callsite in the next iteration.
95 Phase 3: Annotate control flow graph.
96 AutoFDO uses a separate pass to:
97 * Annotate basic block count
98 * Estimate branch probability
100 After the above 3 phases, all profile is readily annotated on the GCC IR.
101 AutoFDO tries to reuse all FDO infrastructure as much as possible to make
102 use of the profile. E.g. it uses existing mechanism to calculate the basic
103 block/edge frequency, as well as the cgraph node/edge count.
106 #define DEFAULT_AUTO_PROFILE_FILE "fbdata.afdo"
107 #define AUTO_PROFILE_VERSION 1
112 /* Represent a source location: (function_decl, lineno). */
113 typedef std::pair
<tree
, unsigned> decl_lineno
;
115 /* Represent an inline stack. vector[0] is the leaf node. */
116 typedef auto_vec
<decl_lineno
> inline_stack
;
118 /* String array that stores function names. */
119 typedef auto_vec
<char *> string_vector
;
121 /* Map from function name's index in string_table to target's
123 typedef std::map
<unsigned, gcov_type
> icall_target_map
;
125 /* Set of gimple stmts. Used to track if the stmt has already been promoted
127 typedef std::set
<gimple
> stmt_set
;
129 /* Represent count info of an inline stack. */
132 /* Sampled count of the inline stack. */
135 /* Map from indirect call target to its sample count. */
136 icall_target_map targets
;
138 /* Whether this inline stack is already used in annotation.
140 Each inline stack should only be used to annotate IR once.
141 This will be enforced when instruction-level discriminator
146 /* operator< for "const char *". */
147 struct string_compare
149 bool operator()(const char *a
, const char *b
) const
151 return strcmp (a
, b
) < 0;
155 /* Store a string array, indexed by string position in the array. */
164 /* For a given string, returns its index. */
165 int get_index (const char *name
) const;
167 /* For a given decl, returns the index of the decl name. */
168 int get_index_by_decl (tree decl
) const;
170 /* For a given index, returns the string. */
171 const char *get_name (int index
) const;
173 /* Read profile, return TRUE on success. */
177 typedef std::map
<const char *, unsigned, string_compare
> string_index_map
;
178 string_vector vector_
;
179 string_index_map map_
;
182 /* Profile of a function instance:
183 1. total_count of the function.
184 2. head_count (entry basic block count) of the function (only valid when
185 function is a top-level function_instance, i.e. it is the original copy
186 instead of the inlined copy).
187 3. map from source location (decl_lineno) to profile (count_info).
188 4. map from callsite to callee function_instance. */
189 class function_instance
192 typedef auto_vec
<function_instance
*> function_instance_stack
;
194 /* Read the profile and return a function_instance with head count as
195 HEAD_COUNT. Recursively read callsites to create nested function_instances
196 too. STACK is used to track the recursive creation process. */
197 static function_instance
*
198 read_function_instance (function_instance_stack
*stack
,
199 gcov_type head_count
);
201 /* Recursively deallocate all callsites (nested function_instances). */
202 ~function_instance ();
221 /* Traverse callsites of the current function_instance to find one at the
222 location of LINENO and callee name represented in DECL. */
223 function_instance
*get_function_instance_by_decl (unsigned lineno
,
226 /* Store the profile info for LOC in INFO. Return TRUE if profile info
228 bool get_count_info (location_t loc
, count_info
*info
) const;
230 /* Read the inlined indirect call target profile for STMT and store it in
231 MAP, return the total count for all inlined indirect calls. */
232 gcov_type
find_icall_target_map (gimple stmt
, icall_target_map
*map
) const;
234 /* Sum of counts that is used during annotation. */
235 gcov_type
total_annotated_count () const;
237 /* Mark LOC as annotated. */
238 void mark_annotated (location_t loc
);
241 /* Callsite, represented as (decl_lineno, callee_function_name_index). */
242 typedef std::pair
<unsigned, unsigned> callsite
;
244 /* Map from callsite to callee function_instance. */
245 typedef std::map
<callsite
, function_instance
*> callsite_map
;
247 function_instance (unsigned name
, gcov_type head_count
)
248 : name_ (name
), total_count_ (0), head_count_ (head_count
)
252 /* Map from source location (decl_lineno) to profile (count_info). */
253 typedef std::map
<unsigned, count_info
> position_count_map
;
255 /* function_instance name index in the string_table. */
258 /* Total sample count. */
259 gcov_type total_count_
;
261 /* Entry BB's sample count. */
262 gcov_type head_count_
;
264 /* Map from callsite location to callee function_instance. */
265 callsite_map callsites
;
267 /* Map from source location to count_info. */
268 position_count_map pos_counts
;
271 /* Profile for all functions. */
272 class autofdo_source_profile
275 static autofdo_source_profile
*
278 autofdo_source_profile
*map
= new autofdo_source_profile ();
286 ~autofdo_source_profile ();
288 /* For a given DECL, returns the top-level function_instance. */
289 function_instance
*get_function_instance_by_decl (tree decl
) const;
291 /* Find count_info for a given gimple STMT. If found, store the count_info
292 in INFO and return true; otherwise return false. */
293 bool get_count_info (gimple stmt
, count_info
*info
) const;
295 /* Find total count of the callee of EDGE. */
296 gcov_type
get_callsite_total_count (struct cgraph_edge
*edge
) const;
298 /* Update value profile INFO for STMT from the inlined indirect callsite.
299 Return true if INFO is updated. */
300 bool update_inlined_ind_target (gimple stmt
, count_info
*info
);
302 /* Mark LOC as annotated. */
303 void mark_annotated (location_t loc
);
306 /* Map from function_instance name index (in string_table) to
307 function_instance. */
308 typedef std::map
<unsigned, function_instance
*> name_function_instance_map
;
310 autofdo_source_profile () {}
312 /* Read AutoFDO profile and returns TRUE on success. */
315 /* Return the function_instance in the profile that correspond to the
318 get_function_instance_by_inline_stack (const inline_stack
&stack
) const;
320 name_function_instance_map map_
;
323 /* Store the strings read from the profile data file. */
324 static string_table
*afdo_string_table
;
326 /* Store the AutoFDO source profile. */
327 static autofdo_source_profile
*afdo_source_profile
;
329 /* gcov_ctr_summary structure to store the profile_info. */
330 static struct gcov_ctr_summary
*afdo_profile_info
;
332 /* Helper functions. */
334 /* Return the original name of NAME: strip the suffix that starts
335 with '.' Caller is responsible for freeing RET. */
338 get_original_name (const char *name
)
340 char *ret
= xstrdup (name
);
341 char *find
= strchr (ret
, '.');
347 /* Return the combined location, which is a 32bit integer in which
348 higher 16 bits stores the line offset of LOC to the start lineno
349 of DECL, The lower 16 bits stores the discrimnator. */
352 get_combined_location (location_t loc
, tree decl
)
354 /* TODO: allow more bits for line and less bits for discriminator. */
355 if (LOCATION_LINE (loc
) - DECL_SOURCE_LINE (decl
) >= (1<<16))
356 warning_at (loc
, OPT_Woverflow
, "Offset exceeds 16 bytes.");
357 return ((LOCATION_LINE (loc
) - DECL_SOURCE_LINE (decl
)) << 16);
360 /* Return the function decl of a given lexical BLOCK. */
363 get_function_decl_from_block (tree block
)
367 if (LOCATION_LOCUS (BLOCK_SOURCE_LOCATION (block
) == UNKNOWN_LOCATION
))
370 for (decl
= BLOCK_ABSTRACT_ORIGIN (block
);
371 decl
&& (TREE_CODE (decl
) == BLOCK
);
372 decl
= BLOCK_ABSTRACT_ORIGIN (decl
))
373 if (TREE_CODE (decl
) == FUNCTION_DECL
)
378 /* Store inline stack for STMT in STACK. */
381 get_inline_stack (location_t locus
, inline_stack
*stack
)
383 if (LOCATION_LOCUS (locus
) == UNKNOWN_LOCATION
)
386 tree block
= LOCATION_BLOCK (locus
);
387 if (block
&& TREE_CODE (block
) == BLOCK
)
390 for (block
= BLOCK_SUPERCONTEXT (block
);
391 block
&& (TREE_CODE (block
) == BLOCK
);
392 block
= BLOCK_SUPERCONTEXT (block
))
394 location_t tmp_locus
= BLOCK_SOURCE_LOCATION (block
);
395 if (LOCATION_LOCUS (tmp_locus
) == UNKNOWN_LOCATION
)
398 tree decl
= get_function_decl_from_block (block
);
400 std::make_pair (decl
, get_combined_location (locus
, decl
)));
406 std::make_pair (current_function_decl
,
407 get_combined_location (locus
, current_function_decl
)));
410 /* Return STMT's combined location, which is a 32bit integer in which
411 higher 16 bits stores the line offset of LOC to the start lineno
412 of DECL, The lower 16 bits stores the discrimnator. */
415 get_relative_location_for_stmt (gimple stmt
)
417 location_t locus
= gimple_location (stmt
);
418 if (LOCATION_LOCUS (locus
) == UNKNOWN_LOCATION
)
419 return UNKNOWN_LOCATION
;
421 for (tree block
= gimple_block (stmt
); block
&& (TREE_CODE (block
) == BLOCK
);
422 block
= BLOCK_SUPERCONTEXT (block
))
423 if (LOCATION_LOCUS (BLOCK_SOURCE_LOCATION (block
)) != UNKNOWN_LOCATION
)
424 return get_combined_location (locus
,
425 get_function_decl_from_block (block
));
426 return get_combined_location (locus
, current_function_decl
);
429 /* Return true if BB contains indirect call. */
432 has_indirect_call (basic_block bb
)
434 gimple_stmt_iterator gsi
;
436 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
438 gimple stmt
= gsi_stmt (gsi
);
439 if (gimple_code (stmt
) == GIMPLE_CALL
&& !gimple_call_internal_p (stmt
)
440 && (gimple_call_fn (stmt
) == NULL
441 || TREE_CODE (gimple_call_fn (stmt
)) != FUNCTION_DECL
))
447 /* Member functions for string_table. */
451 string_table::~string_table ()
453 for (unsigned i
= 0; i
< vector_
.length (); i
++)
458 /* Return the index of a given function NAME. Return -1 if NAME is not
459 found in string table. */
462 string_table::get_index (const char *name
) const
466 string_index_map::const_iterator iter
= map_
.find (name
);
467 if (iter
== map_
.end ())
473 /* Return the index of a given function DECL. Return -1 if DECL is not
474 found in string table. */
477 string_table::get_index_by_decl (tree decl
) const
480 = get_original_name (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
)));
481 int ret
= get_index (name
);
485 ret
= get_index (lang_hooks
.dwarf_name (decl
, 0));
488 if (DECL_ABSTRACT_ORIGIN (decl
))
489 return get_index_by_decl (DECL_ABSTRACT_ORIGIN (decl
));
494 /* Return the function name of a given INDEX. */
497 string_table::get_name (int index
) const
499 gcc_assert (index
> 0 && index
< (int)vector_
.length ());
500 return vector_
[index
];
503 /* Read the string table. Return TRUE if reading is successful. */
506 string_table::read ()
508 if (gcov_read_unsigned () != GCOV_TAG_AFDO_FILE_NAMES
)
510 /* Skip the length of the section. */
511 gcov_read_unsigned ();
512 /* Read in the file name table. */
513 unsigned string_num
= gcov_read_unsigned ();
514 for (unsigned i
= 0; i
< string_num
; i
++)
516 vector_
.safe_push (get_original_name (gcov_read_string ()));
517 map_
[vector_
.last ()] = i
;
522 /* Member functions for function_instance. */
524 function_instance::~function_instance ()
526 for (callsite_map::iterator iter
= callsites
.begin ();
527 iter
!= callsites
.end (); ++iter
)
531 /* Traverse callsites of the current function_instance to find one at the
532 location of LINENO and callee name represented in DECL. */
535 function_instance::get_function_instance_by_decl (unsigned lineno
,
538 int func_name_idx
= afdo_string_table
->get_index_by_decl (decl
);
539 if (func_name_idx
!= -1)
541 callsite_map::const_iterator ret
542 = callsites
.find (std::make_pair (lineno
, func_name_idx
));
543 if (ret
!= callsites
.end ())
547 = afdo_string_table
->get_index (lang_hooks
.dwarf_name (decl
, 0));
548 if (func_name_idx
!= -1)
550 callsite_map::const_iterator ret
551 = callsites
.find (std::make_pair (lineno
, func_name_idx
));
552 if (ret
!= callsites
.end ())
555 if (DECL_ABSTRACT_ORIGIN (decl
))
556 return get_function_instance_by_decl (lineno
, DECL_ABSTRACT_ORIGIN (decl
));
561 /* Store the profile info for LOC in INFO. Return TRUE if profile info
565 function_instance::get_count_info (location_t loc
, count_info
*info
) const
567 position_count_map::const_iterator iter
= pos_counts
.find (loc
);
568 if (iter
== pos_counts
.end ())
570 *info
= iter
->second
;
574 /* Mark LOC as annotated. */
577 function_instance::mark_annotated (location_t loc
)
579 position_count_map::iterator iter
= pos_counts
.find (loc
);
580 if (iter
== pos_counts
.end ())
582 iter
->second
.annotated
= true;
585 /* Read the inlinied indirect call target profile for STMT and store it in
586 MAP, return the total count for all inlined indirect calls. */
589 function_instance::find_icall_target_map (gimple stmt
,
590 icall_target_map
*map
) const
593 unsigned stmt_offset
= get_relative_location_for_stmt (stmt
);
595 for (callsite_map::const_iterator iter
= callsites
.begin ();
596 iter
!= callsites
.end (); ++iter
)
598 unsigned callee
= iter
->second
->name ();
599 /* Check if callsite location match the stmt. */
600 if (iter
->first
.first
!= stmt_offset
)
602 struct cgraph_node
*node
= cgraph_node::get_for_asmname (
603 get_identifier (afdo_string_table
->get_name (callee
)));
606 if (!check_ic_target (stmt
, node
))
608 (*map
)[callee
] = iter
->second
->total_count ();
609 ret
+= iter
->second
->total_count ();
614 /* Read the profile and create a function_instance with head count as
615 HEAD_COUNT. Recursively read callsites to create nested function_instances
616 too. STACK is used to track the recursive creation process. */
618 /* function instance profile format:
622 NUM_POS_COUNTS: 4 bytes
623 NUM_CALLSITES: 4 byte
625 POS_1_OFFSET: 4 bytes
629 VALUE_PROFILE_TYPE: 4 bytes
639 CALLSITE_1_OFFSET: 4 bytes
640 FUNCTION_INSTANCE_PROFILE (nested)
646 function_instance::read_function_instance (function_instance_stack
*stack
,
647 gcov_type head_count
)
649 unsigned name
= gcov_read_unsigned ();
650 unsigned num_pos_counts
= gcov_read_unsigned ();
651 unsigned num_callsites
= gcov_read_unsigned ();
652 function_instance
*s
= new function_instance (name
, head_count
);
653 stack
->safe_push (s
);
655 for (unsigned i
= 0; i
< num_pos_counts
; i
++)
657 unsigned offset
= gcov_read_unsigned () & 0xffff0000;
658 unsigned num_targets
= gcov_read_unsigned ();
659 gcov_type count
= gcov_read_counter ();
660 s
->pos_counts
[offset
].count
= count
;
661 for (unsigned j
= 0; j
< stack
->length (); j
++)
662 (*stack
)[j
]->total_count_
+= count
;
663 for (unsigned j
= 0; j
< num_targets
; j
++)
665 /* Only indirect call target histogram is supported now. */
666 gcov_read_unsigned ();
667 gcov_type target_idx
= gcov_read_counter ();
668 s
->pos_counts
[offset
].targets
[target_idx
] = gcov_read_counter ();
671 for (unsigned i
= 0; i
< num_callsites
; i
++)
673 unsigned offset
= gcov_read_unsigned ();
674 function_instance
*callee_function_instance
675 = read_function_instance (stack
, 0);
676 s
->callsites
[std::make_pair (offset
, callee_function_instance
->name ())]
677 = callee_function_instance
;
683 /* Sum of counts that is used during annotation. */
686 function_instance::total_annotated_count () const
689 for (callsite_map::const_iterator iter
= callsites
.begin ();
690 iter
!= callsites
.end (); ++iter
)
691 ret
+= iter
->second
->total_annotated_count ();
692 for (position_count_map::const_iterator iter
= pos_counts
.begin ();
693 iter
!= pos_counts
.end (); ++iter
)
694 if (iter
->second
.annotated
)
695 ret
+= iter
->second
.count
;
699 /* Member functions for autofdo_source_profile. */
701 autofdo_source_profile::~autofdo_source_profile ()
703 for (name_function_instance_map::const_iterator iter
= map_
.begin ();
704 iter
!= map_
.end (); ++iter
)
708 /* For a given DECL, returns the top-level function_instance. */
711 autofdo_source_profile::get_function_instance_by_decl (tree decl
) const
713 int index
= afdo_string_table
->get_index_by_decl (decl
);
716 name_function_instance_map::const_iterator ret
= map_
.find (index
);
717 return ret
== map_
.end () ? NULL
: ret
->second
;
720 /* Find count_info for a given gimple STMT. If found, store the count_info
721 in INFO and return true; otherwise return false. */
724 autofdo_source_profile::get_count_info (gimple stmt
, count_info
*info
) const
726 if (LOCATION_LOCUS (gimple_location (stmt
)) == cfun
->function_end_locus
)
730 get_inline_stack (gimple_location (stmt
), &stack
);
731 if (stack
.length () == 0)
733 function_instance
*s
= get_function_instance_by_inline_stack (stack
);
736 return s
->get_count_info (stack
[0].second
, info
);
739 /* Mark LOC as annotated. */
742 autofdo_source_profile::mark_annotated (location_t loc
)
745 get_inline_stack (loc
, &stack
);
746 if (stack
.length () == 0)
748 function_instance
*s
= get_function_instance_by_inline_stack (stack
);
751 s
->mark_annotated (stack
[0].second
);
754 /* Update value profile INFO for STMT from the inlined indirect callsite.
755 Return true if INFO is updated. */
758 autofdo_source_profile::update_inlined_ind_target (gimple stmt
,
761 if (LOCATION_LOCUS (gimple_location (stmt
)) == cfun
->function_end_locus
)
765 get_count_info (stmt
, &old_info
);
767 for (icall_target_map::const_iterator iter
= old_info
.targets
.begin ();
768 iter
!= old_info
.targets
.end (); ++iter
)
769 total
+= iter
->second
;
771 /* Program behavior changed, original promoted (and inlined) target is not
772 hot any more. Will avoid promote the original target.
774 To check if original promoted target is still hot, we check the total
775 count of the unpromoted targets (stored in old_info). If it is no less
776 than half of the callsite count (stored in INFO), the original promoted
777 target is considered not hot any more. */
778 if (total
>= info
->count
/ 2)
782 get_inline_stack (gimple_location (stmt
), &stack
);
783 if (stack
.length () == 0)
785 function_instance
*s
= get_function_instance_by_inline_stack (stack
);
788 icall_target_map map
;
789 if (s
->find_icall_target_map (stmt
, &map
) == 0)
791 for (icall_target_map::const_iterator iter
= map
.begin ();
792 iter
!= map
.end (); ++iter
)
793 info
->targets
[iter
->first
] = iter
->second
;
797 /* Find total count of the callee of EDGE. */
800 autofdo_source_profile::get_callsite_total_count (
801 struct cgraph_edge
*edge
) const
804 stack
.safe_push (std::make_pair (edge
->callee
->decl
, 0));
805 get_inline_stack (gimple_location (edge
->call_stmt
), &stack
);
807 function_instance
*s
= get_function_instance_by_inline_stack (stack
);
809 || afdo_string_table
->get_index (IDENTIFIER_POINTER (
810 DECL_ASSEMBLER_NAME (edge
->callee
->decl
))) != s
->name ())
813 return s
->total_count ();
816 /* Read AutoFDO profile and returns TRUE on success. */
818 /* source profile format:
820 GCOV_TAG_AFDO_FUNCTION: 4 bytes
822 NUM_FUNCTIONS: 4 bytes
826 FUNCTION_INSTANCE_N. */
829 autofdo_source_profile::read ()
831 if (gcov_read_unsigned () != GCOV_TAG_AFDO_FUNCTION
)
833 inform (0, "Not expected TAG.");
837 /* Skip the length of the section. */
838 gcov_read_unsigned ();
840 /* Read in the function/callsite profile, and store it in local
842 unsigned function_num
= gcov_read_unsigned ();
843 for (unsigned i
= 0; i
< function_num
; i
++)
845 function_instance::function_instance_stack stack
;
846 function_instance
*s
= function_instance::read_function_instance (
847 &stack
, gcov_read_counter ());
848 afdo_profile_info
->sum_all
+= s
->total_count ();
849 map_
[s
->name ()] = s
;
854 /* Return the function_instance in the profile that correspond to the
858 autofdo_source_profile::get_function_instance_by_inline_stack (
859 const inline_stack
&stack
) const
861 name_function_instance_map::const_iterator iter
= map_
.find (
862 afdo_string_table
->get_index_by_decl (stack
[stack
.length () - 1].first
));
863 if (iter
== map_
.end())
865 function_instance
*s
= iter
->second
;
866 for (unsigned i
= stack
.length() - 1; i
> 0; i
--)
868 s
= s
->get_function_instance_by_decl (
869 stack
[i
].second
, stack
[i
- 1].first
);
876 /* Module profile is only used by LIPO. Here we simply ignore it. */
879 fake_read_autofdo_module_profile ()
881 /* Read in the module info. */
882 gcov_read_unsigned ();
884 /* Skip the length of the section. */
885 gcov_read_unsigned ();
887 /* Read in the file name table. */
888 unsigned total_module_num
= gcov_read_unsigned ();
889 gcc_assert (total_module_num
== 0);
892 /* Read data from profile data file. */
897 if (gcov_open (auto_profile_file
, 1) == 0)
898 error ("Cannot open profile file %s.", auto_profile_file
);
900 if (gcov_read_unsigned () != GCOV_DATA_MAGIC
)
901 error ("AutoFDO profile magic number does not mathch.");
903 /* Skip the version number. */
904 unsigned version
= gcov_read_unsigned ();
905 if (version
!= AUTO_PROFILE_VERSION
)
906 error ("AutoFDO profile version %u does match %u.",
907 version
, AUTO_PROFILE_VERSION
);
909 /* Skip the empty integer. */
910 gcov_read_unsigned ();
913 afdo_string_table
= new string_table ();
914 if (!afdo_string_table
->read())
915 error ("Cannot read string table from %s.", auto_profile_file
);
917 /* autofdo_source_profile. */
918 afdo_source_profile
= autofdo_source_profile::create ();
919 if (afdo_source_profile
== NULL
)
920 error ("Cannot read function profile from %s.", auto_profile_file
);
922 /* autofdo_module_profile. */
923 fake_read_autofdo_module_profile ();
925 /* Read in the working set. */
926 if (gcov_read_unsigned () != GCOV_TAG_AFDO_WORKING_SET
)
927 error ("Cannot read working set from %s.", auto_profile_file
);
929 /* Skip the length of the section. */
930 gcov_read_unsigned ();
931 gcov_working_set_t set
[128];
932 for (unsigned i
= 0; i
< 128; i
++)
934 set
[i
].num_counters
= gcov_read_unsigned ();
935 set
[i
].min_counter
= gcov_read_counter ();
937 add_working_set (set
);
940 /* From AutoFDO profiles, find values inside STMT for that we want to measure
941 histograms for indirect-call optimization.
943 This function is actually served for 2 purposes:
944 Â Â * before annotation, we need to mark histogram, promote and inline
945 Â Â * after annotation, we just need to mark, and let follow-up logic to
946 Â Â Â decide if it needs to promote and inline. */
949 afdo_indirect_call (gimple_stmt_iterator
*gsi
, const icall_target_map
&map
,
952 gimple stmt
= gsi_stmt (*gsi
);
955 if (map
.size () == 0 || gimple_code (stmt
) != GIMPLE_CALL
956 || gimple_call_fndecl (stmt
) != NULL_TREE
)
959 callee
= gimple_call_fn (stmt
);
961 histogram_value hist
= gimple_alloc_histogram_value (
962 cfun
, HIST_TYPE_INDIR_CALL
, stmt
, callee
);
963 hist
->n_counters
= 3;
964 hist
->hvalue
.counters
= XNEWVEC (gcov_type
, hist
->n_counters
);
965 gimple_add_histogram_value (cfun
, stmt
, hist
);
968 icall_target_map::const_iterator max_iter
= map
.end ();
970 for (icall_target_map::const_iterator iter
= map
.begin ();
971 iter
!= map
.end (); ++iter
)
973 total
+= iter
->second
;
974 if (max_iter
== map
.end () || max_iter
->second
< iter
->second
)
978 hist
->hvalue
.counters
[0]
979 = (unsigned long long)afdo_string_table
->get_name (max_iter
->first
);
980 hist
->hvalue
.counters
[1] = max_iter
->second
;
981 hist
->hvalue
.counters
[2] = total
;
986 struct cgraph_edge
*indirect_edge
987 = cgraph_node::get (current_function_decl
)->get_edge (stmt
);
988 struct cgraph_node
*direct_call
= cgraph_node::get_for_asmname (
989 get_identifier ((const char *) hist
->hvalue
.counters
[0]));
991 if (direct_call
== NULL
|| !check_ic_target (stmt
, direct_call
))
993 if (DECL_STRUCT_FUNCTION (direct_call
->decl
) == NULL
)
995 struct cgraph_edge
*new_edge
996 = indirect_edge
->make_speculative (direct_call
, 0, 0);
997 new_edge
->redirect_call_stmt_to_callee ();
998 gimple_remove_histogram_value (cfun
, stmt
, hist
);
999 inline_call (new_edge
, true, NULL
, NULL
, false);
1002 /* From AutoFDO profiles, find values inside STMT for that we want to measure
1003 histograms and adds them to list VALUES. */
1006 afdo_vpt (gimple_stmt_iterator
*gsi
, const icall_target_map
&map
,
1009 afdo_indirect_call (gsi
, map
, transform
);
1012 typedef std::set
<basic_block
> bb_set
;
1013 typedef std::set
<edge
> edge_set
;
1016 is_bb_annotated (const basic_block bb
, const bb_set
&annotated
)
1018 return annotated
.find (bb
) != annotated
.end ();
1022 set_bb_annotated (basic_block bb
, bb_set
*annotated
)
1024 annotated
->insert (bb
);
1028 is_edge_annotated (const edge e
, const edge_set
&annotated
)
1030 return annotated
.find (e
) != annotated
.end ();
1034 set_edge_annotated (edge e
, edge_set
*annotated
)
1036 annotated
->insert (e
);
1039 /* For a given BB, set its execution count. Attach value profile if a stmt
1040 is not in PROMOTED, because we only want to promot an indirect call once.
1041 Return TRUE if BB is annotated. */
1044 afdo_set_bb_count (basic_block bb
, const stmt_set
&promoted
)
1046 gimple_stmt_iterator gsi
;
1049 gcov_type max_count
= 0;
1050 bool has_annotated
= false;
1052 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
1055 gimple stmt
= gsi_stmt (gsi
);
1056 if (gimple_clobber_p (stmt
) || is_gimple_debug (stmt
))
1058 if (afdo_source_profile
->get_count_info (stmt
, &info
))
1060 if (info
.count
> max_count
)
1061 max_count
= info
.count
;
1062 has_annotated
= true;
1063 if (info
.targets
.size () > 0
1064 && promoted
.find (stmt
) == promoted
.end ())
1065 afdo_vpt (&gsi
, info
.targets
, false);
1072 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
1073 afdo_source_profile
->mark_annotated (gimple_location (gsi_stmt (gsi
)));
1074 for (gsi
= gsi_start_phis (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
1076 gimple phi
= gsi_stmt (gsi
);
1078 for (i
= 0; i
< gimple_phi_num_args (phi
); i
++)
1079 afdo_source_profile
->mark_annotated (gimple_phi_arg_location (phi
, i
));
1081 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1082 afdo_source_profile
->mark_annotated (e
->goto_locus
);
1084 bb
->count
= max_count
;
1088 /* BB1 and BB2 are in an equivalent class iff:
1089 1. BB1 dominates BB2.
1090 2. BB2 post-dominates BB1.
1091 3. BB1 and BB2 are in the same loop nest.
1092 This function finds the equivalent class for each basic block, and
1093 stores a pointer to the first BB in its equivalent class. Meanwhile,
1094 set bb counts for the same equivalent class to be idenical. Update
1095 ANNOTATED_BB for the first BB in its equivalent class. */
1098 afdo_find_equiv_class (bb_set
*annotated_bb
)
1102 FOR_ALL_BB_FN (bb
, cfun
)
1105 FOR_ALL_BB_FN (bb
, cfun
)
1107 vec
<basic_block
> dom_bbs
;
1111 if (bb
->aux
!= NULL
)
1114 dom_bbs
= get_dominated_by (CDI_DOMINATORS
, bb
);
1115 FOR_EACH_VEC_ELT (dom_bbs
, i
, bb1
)
1116 if (bb1
->aux
== NULL
&& dominated_by_p (CDI_POST_DOMINATORS
, bb
, bb1
)
1117 && bb1
->loop_father
== bb
->loop_father
)
1120 if (bb1
->count
> bb
->count
&& is_bb_annotated (bb1
, *annotated_bb
))
1122 bb
->count
= MAX (bb
->count
, bb1
->count
);
1123 set_bb_annotated (bb
, annotated_bb
);
1126 dom_bbs
= get_dominated_by (CDI_POST_DOMINATORS
, bb
);
1127 FOR_EACH_VEC_ELT (dom_bbs
, i
, bb1
)
1128 if (bb1
->aux
== NULL
&& dominated_by_p (CDI_DOMINATORS
, bb
, bb1
)
1129 && bb1
->loop_father
== bb
->loop_father
)
1132 if (bb1
->count
> bb
->count
&& is_bb_annotated (bb1
, *annotated_bb
))
1134 bb
->count
= MAX (bb
->count
, bb1
->count
);
1135 set_bb_annotated (bb
, annotated_bb
);
1141 /* If a basic block's count is known, and only one of its in/out edges' count
1142 is unknown, its count can be calculated. Meanwhile, if all of the in/out
1143 edges' counts are known, then the basic block's unknown count can also be
1145 IS_SUCC is true if out edges of a basic blocks are examined.
1146 Update ANNOTATED_BB and ANNOTATED_EDGE accordingly.
1147 Return TRUE if any basic block/edge count is changed. */
1150 afdo_propagate_edge (bool is_succ
, bb_set
*annotated_bb
,
1151 edge_set
*annotated_edge
)
1154 bool changed
= false;
1156 FOR_EACH_BB_FN (bb
, cfun
)
1158 edge e
, unknown_edge
= NULL
;
1160 int num_unknown_edge
= 0;
1161 gcov_type total_known_count
= 0;
1163 FOR_EACH_EDGE (e
, ei
, is_succ
? bb
->succs
: bb
->preds
)
1164 if (!is_edge_annotated (e
, *annotated_edge
))
1165 num_unknown_edge
++, unknown_edge
= e
;
1167 total_known_count
+= e
->count
;
1169 if (num_unknown_edge
== 0)
1171 if (total_known_count
> bb
->count
)
1173 bb
->count
= total_known_count
;
1176 if (!is_bb_annotated (bb
, *annotated_bb
))
1178 set_bb_annotated (bb
, annotated_bb
);
1182 else if (num_unknown_edge
== 1 && is_bb_annotated (bb
, *annotated_bb
))
1184 if (bb
->count
>= total_known_count
)
1185 unknown_edge
->count
= bb
->count
- total_known_count
;
1187 unknown_edge
->count
= 0;
1188 set_edge_annotated (unknown_edge
, annotated_edge
);
1195 /* Special propagation for circuit expressions. Because GCC translates
1196 control flow into data flow for circuit expressions. E.g.
1203 will be translated into:
1218 tmp = PHI (0 (BB1), 0 (BB.t1), 1 (BB.t2)
1224 In this case, we need to propagate through PHI to determine the edge
1225 count of BB1->BB.t1, BB.t1->BB.t2.
1226 Update ANNOTATED_EDGE accordingly. */
1229 afdo_propagate_circuit (const bb_set
&annotated_bb
, edge_set
*annotated_edge
)
1232 FOR_ALL_BB_FN (bb
, cfun
)
1235 tree cmp_rhs
, cmp_lhs
;
1236 gimple cmp_stmt
= last_stmt (bb
);
1240 if (!cmp_stmt
|| gimple_code (cmp_stmt
) != GIMPLE_COND
)
1242 cmp_rhs
= gimple_cond_rhs (cmp_stmt
);
1243 cmp_lhs
= gimple_cond_lhs (cmp_stmt
);
1244 if (!TREE_CONSTANT (cmp_rhs
)
1245 || !(integer_zerop (cmp_rhs
) || integer_onep (cmp_rhs
)))
1247 if (TREE_CODE (cmp_lhs
) != SSA_NAME
)
1249 if (!is_bb_annotated (bb
, annotated_bb
))
1251 phi_stmt
= SSA_NAME_DEF_STMT (cmp_lhs
);
1252 while (phi_stmt
&& gimple_code (phi_stmt
) == GIMPLE_ASSIGN
1253 && gimple_assign_single_p (phi_stmt
)
1254 && TREE_CODE (gimple_assign_rhs1 (phi_stmt
)) == SSA_NAME
)
1255 phi_stmt
= SSA_NAME_DEF_STMT (gimple_assign_rhs1 (phi_stmt
));
1256 if (!phi_stmt
|| gimple_code (phi_stmt
) != GIMPLE_PHI
)
1258 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1260 unsigned i
, total
= 0;
1262 bool check_value_one
= (((integer_onep (cmp_rhs
))
1263 ^ (gimple_cond_code (cmp_stmt
) == EQ_EXPR
))
1264 ^ ((e
->flags
& EDGE_TRUE_VALUE
) != 0));
1265 if (!is_edge_annotated (e
, *annotated_edge
))
1267 for (i
= 0; i
< gimple_phi_num_args (phi_stmt
); i
++)
1269 tree val
= gimple_phi_arg_def (phi_stmt
, i
);
1270 edge ep
= gimple_phi_arg_edge (phi_stmt
, i
);
1272 if (!TREE_CONSTANT (val
)
1273 || !(integer_zerop (val
) || integer_onep (val
)))
1275 if (check_value_one
^ integer_onep (val
))
1279 if (e
->probability
== 0 && !is_edge_annotated (ep
, *annotated_edge
))
1281 ep
->probability
= 0;
1283 set_edge_annotated (ep
, annotated_edge
);
1286 if (total
== 1 && !is_edge_annotated (only_one
, *annotated_edge
))
1288 only_one
->probability
= e
->probability
;
1289 only_one
->count
= e
->count
;
1290 set_edge_annotated (only_one
, annotated_edge
);
1296 /* Propagate the basic block count and edge count on the control flow
1297 graph. We do the propagation iteratively until stablize. */
1300 afdo_propagate (bb_set
*annotated_bb
, edge_set
*annotated_edge
)
1303 bool changed
= true;
1306 FOR_ALL_BB_FN (bb
, cfun
)
1308 bb
->count
= ((basic_block
)bb
->aux
)->count
;
1309 if (is_bb_annotated ((const basic_block
)bb
->aux
, *annotated_bb
))
1310 set_bb_annotated (bb
, annotated_bb
);
1313 while (changed
&& i
++ < 10)
1317 if (afdo_propagate_edge (true, annotated_bb
, annotated_edge
))
1319 if (afdo_propagate_edge (false, annotated_bb
, annotated_edge
))
1321 afdo_propagate_circuit (*annotated_bb
, annotated_edge
);
1325 /* Propagate counts on control flow graph and calculate branch
1329 afdo_calculate_branch_prob (bb_set
*annotated_bb
, edge_set
*annotated_edge
)
1332 bool has_sample
= false;
1334 FOR_EACH_BB_FN (bb
, cfun
)
1341 calculate_dominance_info (CDI_POST_DOMINATORS
);
1342 calculate_dominance_info (CDI_DOMINATORS
);
1343 loop_optimizer_init (0);
1345 afdo_find_equiv_class (annotated_bb
);
1346 afdo_propagate (annotated_bb
, annotated_edge
);
1348 FOR_EACH_BB_FN (bb
, cfun
)
1352 int num_unknown_succ
= 0;
1353 gcov_type total_count
= 0;
1355 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1357 if (!is_edge_annotated (e
, *annotated_edge
))
1360 total_count
+= e
->count
;
1362 if (num_unknown_succ
== 0 && total_count
> 0)
1364 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1365 e
->probability
= (double)e
->count
* REG_BR_PROB_BASE
/ total_count
;
1368 FOR_ALL_BB_FN (bb
, cfun
)
1373 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1374 e
->count
= (double)bb
->count
* e
->probability
/ REG_BR_PROB_BASE
;
1378 loop_optimizer_finalize ();
1379 free_dominance_info (CDI_DOMINATORS
);
1380 free_dominance_info (CDI_POST_DOMINATORS
);
1383 /* Perform value profile transformation using AutoFDO profile. Add the
1384 promoted stmts to PROMOTED_STMTS. Return TRUE if there is any
1385 indirect call promoted. */
1388 afdo_vpt_for_early_inline (stmt_set
*promoted_stmts
)
1391 if (afdo_source_profile
->get_function_instance_by_decl (
1392 current_function_decl
) == NULL
)
1395 compute_inline_parameters (cgraph_node::get (current_function_decl
), true);
1397 bool has_vpt
= false;
1398 FOR_EACH_BB_FN (bb
, cfun
)
1400 if (!has_indirect_call (bb
))
1402 gimple_stmt_iterator gsi
;
1404 gcov_type bb_count
= 0;
1405 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
1408 gimple stmt
= gsi_stmt (gsi
);
1409 if (afdo_source_profile
->get_count_info (stmt
, &info
))
1410 bb_count
= MAX (bb_count
, info
.count
);
1413 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
1415 gimple stmt
= gsi_stmt (gsi
);
1416 /* IC_promotion and early_inline_2 is done in multiple iterations.
1417 No need to promoted the stmt if its in promoted_stmts (means
1418 it is already been promoted in the previous iterations). */
1419 if (gimple_code (stmt
) != GIMPLE_CALL
|| gimple_call_fn (stmt
) == NULL
1420 || TREE_CODE (gimple_call_fn (stmt
)) == FUNCTION_DECL
1421 || promoted_stmts
->find (stmt
) != promoted_stmts
->end ())
1425 afdo_source_profile
->get_count_info (stmt
, &info
);
1426 info
.count
= bb_count
;
1427 if (afdo_source_profile
->update_inlined_ind_target (stmt
, &info
))
1429 /* Promote the indirect call and update the promoted_stmts. */
1430 promoted_stmts
->insert (stmt
);
1431 afdo_vpt (&gsi
, info
.targets
, true);
1438 optimize_inline_calls (current_function_decl
);
1445 /* Annotate auto profile to the control flow graph. Do not annotate value
1446 profile for stmts in PROMOTED_STMTS. */
1449 afdo_annotate_cfg (const stmt_set
&promoted_stmts
)
1452 bb_set annotated_bb
;
1453 edge_set annotated_edge
;
1454 const function_instance
*s
1455 = afdo_source_profile
->get_function_instance_by_decl (
1456 current_function_decl
);
1460 cgraph_node::get (current_function_decl
)->count
= s
->head_count ();
1461 ENTRY_BLOCK_PTR_FOR_FN (cfun
)->count
= s
->head_count ();
1462 gcov_type max_count
= ENTRY_BLOCK_PTR_FOR_FN (cfun
)->count
;
1464 FOR_EACH_BB_FN (bb
, cfun
)
1470 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1473 if (afdo_set_bb_count (bb
, promoted_stmts
))
1474 set_bb_annotated (bb
, &annotated_bb
);
1475 if (bb
->count
> max_count
)
1476 max_count
= bb
->count
;
1478 if (ENTRY_BLOCK_PTR_FOR_FN (cfun
)->count
1479 > ENTRY_BLOCK_PTR_FOR_FN (cfun
)->next_bb
->count
)
1481 ENTRY_BLOCK_PTR_FOR_FN (cfun
)->next_bb
->count
1482 = ENTRY_BLOCK_PTR_FOR_FN (cfun
)->count
;
1483 set_bb_annotated (ENTRY_BLOCK_PTR_FOR_FN (cfun
)->next_bb
, &annotated_bb
);
1485 if (ENTRY_BLOCK_PTR_FOR_FN (cfun
)->count
1486 > EXIT_BLOCK_PTR_FOR_FN (cfun
)->prev_bb
->count
)
1488 EXIT_BLOCK_PTR_FOR_FN (cfun
)->prev_bb
->count
1489 = ENTRY_BLOCK_PTR_FOR_FN (cfun
)->count
;
1490 set_bb_annotated (EXIT_BLOCK_PTR_FOR_FN (cfun
)->prev_bb
, &annotated_bb
);
1492 afdo_source_profile
->mark_annotated (
1493 DECL_SOURCE_LOCATION (current_function_decl
));
1494 afdo_source_profile
->mark_annotated (cfun
->function_start_locus
);
1495 afdo_source_profile
->mark_annotated (cfun
->function_end_locus
);
1498 afdo_calculate_branch_prob (&annotated_bb
, &annotated_edge
);
1500 profile_status_for_fn (cfun
) = PROFILE_READ
;
1502 if (flag_value_profile_transformations
)
1503 gimple_value_profile_transformations ();
1506 /* Wrapper function to invoke early inliner. */
1511 compute_inline_parameters (cgraph_node::get (current_function_decl
), true);
1512 unsigned todo
= early_inliner (cfun
);
1513 if (todo
& TODO_update_ssa_any
)
1514 update_ssa (TODO_update_ssa
);
1517 /* Use AutoFDO profile to annoate the control flow graph.
1518 Return the todo flag. */
1523 struct cgraph_node
*node
;
1525 if (symtab
->state
== FINISHED
)
1528 init_node_map (true);
1529 profile_info
= autofdo::afdo_profile_info
;
1531 FOR_EACH_FUNCTION (node
)
1533 if (!gimple_has_body_p (node
->decl
))
1536 /* Don't profile functions produced for builtin stuff. */
1537 if (DECL_SOURCE_LOCATION (node
->decl
) == BUILTINS_LOCATION
)
1540 push_cfun (DECL_STRUCT_FUNCTION (node
->decl
));
1542 /* First do indirect call promotion and early inline to make the
1543 IR match the profiled binary before actual annotation.
1545 This is needed because an indirect call might have been promoted
1546 and inlined in the profiled binary. If we do not promote and
1547 inline these indirect calls before annotation, the profile for
1548 these promoted functions will be lost.
1550 e.g. foo() --indirect_call--> bar()
1551 In profiled binary, the callsite is promoted and inlined, making
1552 the profile look like:
1562 Before AutoFDO pass, loc_foo_2 is not promoted thus not inlined.
1563 If we perform annotation on it, the profile inside bar@loc_foo2
1566 To avoid this, we promote loc_foo_2 and inline the promoted bar
1567 function before annotation, so the profile inside bar@loc_foo2
1569 autofdo::stmt_set promoted_stmts
;
1570 for (int i
= 0; i
< PARAM_VALUE (PARAM_EARLY_INLINER_MAX_ITERATIONS
); i
++)
1572 if (!flag_value_profile_transformations
1573 || !autofdo::afdo_vpt_for_early_inline (&promoted_stmts
))
1579 autofdo::afdo_annotate_cfg (promoted_stmts
);
1580 compute_function_frequency ();
1581 update_ssa (TODO_update_ssa
);
1583 /* Local pure-const may imply need to fixup the cfg. */
1584 if (execute_fixup_cfg () & TODO_cleanup_cfg
)
1585 cleanup_tree_cfg ();
1587 free_dominance_info (CDI_DOMINATORS
);
1588 free_dominance_info (CDI_POST_DOMINATORS
);
1589 cgraph_edge::rebuild_edges ();
1593 return TODO_rebuild_cgraph_edges
;
1595 } /* namespace autofdo. */
1597 /* Read the profile from the profile data file. */
1600 read_autofdo_file (void)
1602 if (auto_profile_file
== NULL
)
1603 auto_profile_file
= DEFAULT_AUTO_PROFILE_FILE
;
1605 autofdo::afdo_profile_info
= (struct gcov_ctr_summary
*)xcalloc (
1606 1, sizeof (struct gcov_ctr_summary
));
1607 autofdo::afdo_profile_info
->runs
= 1;
1608 autofdo::afdo_profile_info
->sum_max
= 0;
1609 autofdo::afdo_profile_info
->sum_all
= 0;
1611 /* Read the profile from the profile file. */
1612 autofdo::read_profile ();
1615 /* Free the resources. */
1618 end_auto_profile (void)
1620 delete autofdo::afdo_source_profile
;
1621 delete autofdo::afdo_string_table
;
1622 profile_info
= NULL
;
1625 /* Returns TRUE if EDGE is hot enough to be inlined early. */
1628 afdo_callsite_hot_enough_for_early_inline (struct cgraph_edge
*edge
)
1631 = autofdo::afdo_source_profile
->get_callsite_total_count (edge
);
1635 const struct gcov_ctr_summary
*saved_profile_info
= profile_info
;
1636 /* At earling inline stage, profile_info is not set yet. We need to
1637 temporarily set it to afdo_profile_info to calculate hotness. */
1638 profile_info
= autofdo::afdo_profile_info
;
1639 is_hot
= maybe_hot_count_p (NULL
, count
);
1640 profile_info
= saved_profile_info
;
1650 const pass_data pass_data_ipa_auto_profile
= {
1651 SIMPLE_IPA_PASS
, "afdo", /* name */
1652 OPTGROUP_NONE
, /* optinfo_flags */
1653 TV_IPA_AUTOFDO
, /* tv_id */
1654 0, /* properties_required */
1655 0, /* properties_provided */
1656 0, /* properties_destroyed */
1657 0, /* todo_flags_start */
1658 0, /* todo_flags_finish */
1661 class pass_ipa_auto_profile
: public simple_ipa_opt_pass
1664 pass_ipa_auto_profile (gcc::context
*ctxt
)
1665 : simple_ipa_opt_pass (pass_data_ipa_auto_profile
, ctxt
)
1669 /* opt_pass methods: */
1673 return flag_auto_profile
;
1675 virtual unsigned int
1676 execute (function
*)
1678 return autofdo::auto_profile ();
1680 }; // class pass_ipa_auto_profile
1684 simple_ipa_opt_pass
*
1685 make_pass_ipa_auto_profile (gcc::context
*ctxt
)
1687 return new pass_ipa_auto_profile (ctxt
);