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"
38 #include "hard-reg-set.h"
41 #include "dominance.h"
43 #include "basic-block.h"
44 #include "diagnostic-core.h"
47 #include "langhooks.h"
49 #include "tree-pass.h"
51 #include "tree-ssa-alias.h"
53 #include "tree-cfgcleanup.h"
54 #include "tree-ssa-operands.h"
55 #include "tree-into-ssa.h"
56 #include "internal-fn.h"
58 #include "gimple-expr.h"
60 #include "gimple-iterator.h"
61 #include "gimple-ssa.h"
63 #include "value-prof.h"
66 #include "ipa-inline.h"
67 #include "tree-inline.h"
68 #include "stringpool.h"
69 #include "auto-profile.h"
71 /* The following routines implements AutoFDO optimization.
73 This optimization uses sampling profiles to annotate basic block counts
74 and uses heuristics to estimate branch probabilities.
76 There are three phases in AutoFDO:
78 Phase 1: Read profile from the profile data file.
79 The following info is read from the profile datafile:
80 * string_table: a map between function name and its index.
81 * autofdo_source_profile: a map from function_instance name to
82 function_instance. This is represented as a forest of
84 * WorkingSet: a histogram of how many instructions are covered for a
85 given percentage of total cycles. This is describing the binary
86 level information (not source level). This info is used to help
87 decide if we want aggressive optimizations that could increase
88 code footprint (e.g. loop unroll etc.)
89 A function instance is an instance of function that could either be a
90 standalone symbol, or a clone of a function that is inlined into another
93 Phase 2: Early inline + valur profile transformation.
94 Early inline uses autofdo_source_profile to find if a callsite is:
95 * inlined in the profiled binary.
96 * callee body is hot in the profiling run.
97 If both condition satisfies, early inline will inline the callsite
98 regardless of the code growth.
99 Phase 2 is an iterative process. During each iteration, we also check
100 if an indirect callsite is promoted and inlined in the profiling run.
101 If yes, vpt will happen to force promote it and in the next iteration,
102 einline will inline the promoted callsite in the next iteration.
104 Phase 3: Annotate control flow graph.
105 AutoFDO uses a separate pass to:
106 * Annotate basic block count
107 * Estimate branch probability
109 After the above 3 phases, all profile is readily annotated on the GCC IR.
110 AutoFDO tries to reuse all FDO infrastructure as much as possible to make
111 use of the profile. E.g. it uses existing mechanism to calculate the basic
112 block/edge frequency, as well as the cgraph node/edge count.
115 #define DEFAULT_AUTO_PROFILE_FILE "fbdata.afdo"
116 #define AUTO_PROFILE_VERSION 1
121 /* Represent a source location: (function_decl, lineno). */
122 typedef std::pair
<tree
, unsigned> decl_lineno
;
124 /* Represent an inline stack. vector[0] is the leaf node. */
125 typedef auto_vec
<decl_lineno
> inline_stack
;
127 /* String array that stores function names. */
128 typedef auto_vec
<char *> string_vector
;
130 /* Map from function name's index in string_table to target's
132 typedef std::map
<unsigned, gcov_type
> icall_target_map
;
134 /* Set of gimple stmts. Used to track if the stmt has already been promoted
136 typedef std::set
<gimple
> stmt_set
;
138 /* Represent count info of an inline stack. */
141 /* Sampled count of the inline stack. */
144 /* Map from indirect call target to its sample count. */
145 icall_target_map targets
;
147 /* Whether this inline stack is already used in annotation.
149 Each inline stack should only be used to annotate IR once.
150 This will be enforced when instruction-level discriminator
155 /* operator< for "const char *". */
156 struct string_compare
158 bool operator()(const char *a
, const char *b
) const
160 return strcmp (a
, b
) < 0;
164 /* Store a string array, indexed by string position in the array. */
173 /* For a given string, returns its index. */
174 int get_index (const char *name
) const;
176 /* For a given decl, returns the index of the decl name. */
177 int get_index_by_decl (tree decl
) const;
179 /* For a given index, returns the string. */
180 const char *get_name (int index
) const;
182 /* Read profile, return TRUE on success. */
186 typedef std::map
<const char *, unsigned, string_compare
> string_index_map
;
187 string_vector vector_
;
188 string_index_map map_
;
191 /* Profile of a function instance:
192 1. total_count of the function.
193 2. head_count (entry basic block count) of the function (only valid when
194 function is a top-level function_instance, i.e. it is the original copy
195 instead of the inlined copy).
196 3. map from source location (decl_lineno) to profile (count_info).
197 4. map from callsite to callee function_instance. */
198 class function_instance
201 typedef auto_vec
<function_instance
*> function_instance_stack
;
203 /* Read the profile and return a function_instance with head count as
204 HEAD_COUNT. Recursively read callsites to create nested function_instances
205 too. STACK is used to track the recursive creation process. */
206 static function_instance
*
207 read_function_instance (function_instance_stack
*stack
,
208 gcov_type head_count
);
210 /* Recursively deallocate all callsites (nested function_instances). */
211 ~function_instance ();
230 /* Traverse callsites of the current function_instance to find one at the
231 location of LINENO and callee name represented in DECL. */
232 function_instance
*get_function_instance_by_decl (unsigned lineno
,
235 /* Store the profile info for LOC in INFO. Return TRUE if profile info
237 bool get_count_info (location_t loc
, count_info
*info
) const;
239 /* Read the inlined indirect call target profile for STMT and store it in
240 MAP, return the total count for all inlined indirect calls. */
241 gcov_type
find_icall_target_map (gimple stmt
, icall_target_map
*map
) const;
243 /* Sum of counts that is used during annotation. */
244 gcov_type
total_annotated_count () const;
246 /* Mark LOC as annotated. */
247 void mark_annotated (location_t loc
);
250 /* Callsite, represented as (decl_lineno, callee_function_name_index). */
251 typedef std::pair
<unsigned, unsigned> callsite
;
253 /* Map from callsite to callee function_instance. */
254 typedef std::map
<callsite
, function_instance
*> callsite_map
;
256 function_instance (unsigned name
, gcov_type head_count
)
257 : name_ (name
), total_count_ (0), head_count_ (head_count
)
261 /* Map from source location (decl_lineno) to profile (count_info). */
262 typedef std::map
<unsigned, count_info
> position_count_map
;
264 /* function_instance name index in the string_table. */
267 /* Total sample count. */
268 gcov_type total_count_
;
270 /* Entry BB's sample count. */
271 gcov_type head_count_
;
273 /* Map from callsite location to callee function_instance. */
274 callsite_map callsites
;
276 /* Map from source location to count_info. */
277 position_count_map pos_counts
;
280 /* Profile for all functions. */
281 class autofdo_source_profile
284 static autofdo_source_profile
*
287 autofdo_source_profile
*map
= new autofdo_source_profile ();
295 ~autofdo_source_profile ();
297 /* For a given DECL, returns the top-level function_instance. */
298 function_instance
*get_function_instance_by_decl (tree decl
) const;
300 /* Find count_info for a given gimple STMT. If found, store the count_info
301 in INFO and return true; otherwise return false. */
302 bool get_count_info (gimple stmt
, count_info
*info
) const;
304 /* Find total count of the callee of EDGE. */
305 gcov_type
get_callsite_total_count (struct cgraph_edge
*edge
) const;
307 /* Update value profile INFO for STMT from the inlined indirect callsite.
308 Return true if INFO is updated. */
309 bool update_inlined_ind_target (gimple stmt
, count_info
*info
);
311 /* Mark LOC as annotated. */
312 void mark_annotated (location_t loc
);
315 /* Map from function_instance name index (in string_table) to
316 function_instance. */
317 typedef std::map
<unsigned, function_instance
*> name_function_instance_map
;
319 autofdo_source_profile () {}
321 /* Read AutoFDO profile and returns TRUE on success. */
324 /* Return the function_instance in the profile that correspond to the
327 get_function_instance_by_inline_stack (const inline_stack
&stack
) const;
329 name_function_instance_map map_
;
332 /* Store the strings read from the profile data file. */
333 static string_table
*afdo_string_table
;
335 /* Store the AutoFDO source profile. */
336 static autofdo_source_profile
*afdo_source_profile
;
338 /* gcov_ctr_summary structure to store the profile_info. */
339 static struct gcov_ctr_summary
*afdo_profile_info
;
341 /* Helper functions. */
343 /* Return the original name of NAME: strip the suffix that starts
344 with '.' Caller is responsible for freeing RET. */
347 get_original_name (const char *name
)
349 char *ret
= xstrdup (name
);
350 char *find
= strchr (ret
, '.');
356 /* Return the combined location, which is a 32bit integer in which
357 higher 16 bits stores the line offset of LOC to the start lineno
358 of DECL, The lower 16 bits stores the discrimnator. */
361 get_combined_location (location_t loc
, tree decl
)
363 /* TODO: allow more bits for line and less bits for discriminator. */
364 if (LOCATION_LINE (loc
) - DECL_SOURCE_LINE (decl
) >= (1<<16))
365 warning_at (loc
, OPT_Woverflow
, "Offset exceeds 16 bytes.");
366 return ((LOCATION_LINE (loc
) - DECL_SOURCE_LINE (decl
)) << 16);
369 /* Return the function decl of a given lexical BLOCK. */
372 get_function_decl_from_block (tree block
)
376 if (LOCATION_LOCUS (BLOCK_SOURCE_LOCATION (block
) == UNKNOWN_LOCATION
))
379 for (decl
= BLOCK_ABSTRACT_ORIGIN (block
);
380 decl
&& (TREE_CODE (decl
) == BLOCK
);
381 decl
= BLOCK_ABSTRACT_ORIGIN (decl
))
382 if (TREE_CODE (decl
) == FUNCTION_DECL
)
387 /* Store inline stack for STMT in STACK. */
390 get_inline_stack (location_t locus
, inline_stack
*stack
)
392 if (LOCATION_LOCUS (locus
) == UNKNOWN_LOCATION
)
395 tree block
= LOCATION_BLOCK (locus
);
396 if (block
&& TREE_CODE (block
) == BLOCK
)
399 for (block
= BLOCK_SUPERCONTEXT (block
);
400 block
&& (TREE_CODE (block
) == BLOCK
);
401 block
= BLOCK_SUPERCONTEXT (block
))
403 location_t tmp_locus
= BLOCK_SOURCE_LOCATION (block
);
404 if (LOCATION_LOCUS (tmp_locus
) == UNKNOWN_LOCATION
)
407 tree decl
= get_function_decl_from_block (block
);
409 std::make_pair (decl
, get_combined_location (locus
, decl
)));
415 std::make_pair (current_function_decl
,
416 get_combined_location (locus
, current_function_decl
)));
419 /* Return STMT's combined location, which is a 32bit integer in which
420 higher 16 bits stores the line offset of LOC to the start lineno
421 of DECL, The lower 16 bits stores the discrimnator. */
424 get_relative_location_for_stmt (gimple stmt
)
426 location_t locus
= gimple_location (stmt
);
427 if (LOCATION_LOCUS (locus
) == UNKNOWN_LOCATION
)
428 return UNKNOWN_LOCATION
;
430 for (tree block
= gimple_block (stmt
); block
&& (TREE_CODE (block
) == BLOCK
);
431 block
= BLOCK_SUPERCONTEXT (block
))
432 if (LOCATION_LOCUS (BLOCK_SOURCE_LOCATION (block
)) != UNKNOWN_LOCATION
)
433 return get_combined_location (locus
,
434 get_function_decl_from_block (block
));
435 return get_combined_location (locus
, current_function_decl
);
438 /* Return true if BB contains indirect call. */
441 has_indirect_call (basic_block bb
)
443 gimple_stmt_iterator gsi
;
445 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
447 gimple stmt
= gsi_stmt (gsi
);
448 if (gimple_code (stmt
) == GIMPLE_CALL
&& !gimple_call_internal_p (stmt
)
449 && (gimple_call_fn (stmt
) == NULL
450 || TREE_CODE (gimple_call_fn (stmt
)) != FUNCTION_DECL
))
456 /* Member functions for string_table. */
460 string_table::~string_table ()
462 for (unsigned i
= 0; i
< vector_
.length (); i
++)
467 /* Return the index of a given function NAME. Return -1 if NAME is not
468 found in string table. */
471 string_table::get_index (const char *name
) const
475 string_index_map::const_iterator iter
= map_
.find (name
);
476 if (iter
== map_
.end ())
482 /* Return the index of a given function DECL. Return -1 if DECL is not
483 found in string table. */
486 string_table::get_index_by_decl (tree decl
) const
489 = get_original_name (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
)));
490 int ret
= get_index (name
);
494 ret
= get_index (lang_hooks
.dwarf_name (decl
, 0));
497 if (DECL_ABSTRACT_ORIGIN (decl
))
498 return get_index_by_decl (DECL_ABSTRACT_ORIGIN (decl
));
503 /* Return the function name of a given INDEX. */
506 string_table::get_name (int index
) const
508 gcc_assert (index
> 0 && index
< (int)vector_
.length ());
509 return vector_
[index
];
512 /* Read the string table. Return TRUE if reading is successful. */
515 string_table::read ()
517 if (gcov_read_unsigned () != GCOV_TAG_AFDO_FILE_NAMES
)
519 /* Skip the length of the section. */
520 gcov_read_unsigned ();
521 /* Read in the file name table. */
522 unsigned string_num
= gcov_read_unsigned ();
523 for (unsigned i
= 0; i
< string_num
; i
++)
525 vector_
.safe_push (get_original_name (gcov_read_string ()));
526 map_
[vector_
.last ()] = i
;
531 /* Member functions for function_instance. */
533 function_instance::~function_instance ()
535 for (callsite_map::iterator iter
= callsites
.begin ();
536 iter
!= callsites
.end (); ++iter
)
540 /* Traverse callsites of the current function_instance to find one at the
541 location of LINENO and callee name represented in DECL. */
544 function_instance::get_function_instance_by_decl (unsigned lineno
,
547 int func_name_idx
= afdo_string_table
->get_index_by_decl (decl
);
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 ())
556 = afdo_string_table
->get_index (lang_hooks
.dwarf_name (decl
, 0));
557 if (func_name_idx
!= -1)
559 callsite_map::const_iterator ret
560 = callsites
.find (std::make_pair (lineno
, func_name_idx
));
561 if (ret
!= callsites
.end ())
564 if (DECL_ABSTRACT_ORIGIN (decl
))
565 return get_function_instance_by_decl (lineno
, DECL_ABSTRACT_ORIGIN (decl
));
570 /* Store the profile info for LOC in INFO. Return TRUE if profile info
574 function_instance::get_count_info (location_t loc
, count_info
*info
) const
576 position_count_map::const_iterator iter
= pos_counts
.find (loc
);
577 if (iter
== pos_counts
.end ())
579 *info
= iter
->second
;
583 /* Mark LOC as annotated. */
586 function_instance::mark_annotated (location_t loc
)
588 position_count_map::iterator iter
= pos_counts
.find (loc
);
589 if (iter
== pos_counts
.end ())
591 iter
->second
.annotated
= true;
594 /* Read the inlinied indirect call target profile for STMT and store it in
595 MAP, return the total count for all inlined indirect calls. */
598 function_instance::find_icall_target_map (gimple stmt
,
599 icall_target_map
*map
) const
602 unsigned stmt_offset
= get_relative_location_for_stmt (stmt
);
604 for (callsite_map::const_iterator iter
= callsites
.begin ();
605 iter
!= callsites
.end (); ++iter
)
607 unsigned callee
= iter
->second
->name ();
608 /* Check if callsite location match the stmt. */
609 if (iter
->first
.first
!= stmt_offset
)
611 struct cgraph_node
*node
= cgraph_node::get_for_asmname (
612 get_identifier (afdo_string_table
->get_name (callee
)));
615 if (!check_ic_target (stmt
, node
))
617 (*map
)[callee
] = iter
->second
->total_count ();
618 ret
+= iter
->second
->total_count ();
623 /* Read the profile and create a function_instance with head count as
624 HEAD_COUNT. Recursively read callsites to create nested function_instances
625 too. STACK is used to track the recursive creation process. */
627 /* function instance profile format:
631 NUM_POS_COUNTS: 4 bytes
632 NUM_CALLSITES: 4 byte
634 POS_1_OFFSET: 4 bytes
638 VALUE_PROFILE_TYPE: 4 bytes
648 CALLSITE_1_OFFSET: 4 bytes
649 FUNCTION_INSTANCE_PROFILE (nested)
655 function_instance::read_function_instance (function_instance_stack
*stack
,
656 gcov_type head_count
)
658 unsigned name
= gcov_read_unsigned ();
659 unsigned num_pos_counts
= gcov_read_unsigned ();
660 unsigned num_callsites
= gcov_read_unsigned ();
661 function_instance
*s
= new function_instance (name
, head_count
);
662 stack
->safe_push (s
);
664 for (unsigned i
= 0; i
< num_pos_counts
; i
++)
666 unsigned offset
= gcov_read_unsigned () & 0xffff0000;
667 unsigned num_targets
= gcov_read_unsigned ();
668 gcov_type count
= gcov_read_counter ();
669 s
->pos_counts
[offset
].count
= count
;
670 for (unsigned j
= 0; j
< stack
->length (); j
++)
671 (*stack
)[j
]->total_count_
+= count
;
672 for (unsigned j
= 0; j
< num_targets
; j
++)
674 /* Only indirect call target histogram is supported now. */
675 gcov_read_unsigned ();
676 gcov_type target_idx
= gcov_read_counter ();
677 s
->pos_counts
[offset
].targets
[target_idx
] = gcov_read_counter ();
680 for (unsigned i
= 0; i
< num_callsites
; i
++)
682 unsigned offset
= gcov_read_unsigned ();
683 function_instance
*callee_function_instance
684 = read_function_instance (stack
, 0);
685 s
->callsites
[std::make_pair (offset
, callee_function_instance
->name ())]
686 = callee_function_instance
;
692 /* Sum of counts that is used during annotation. */
695 function_instance::total_annotated_count () const
698 for (callsite_map::const_iterator iter
= callsites
.begin ();
699 iter
!= callsites
.end (); ++iter
)
700 ret
+= iter
->second
->total_annotated_count ();
701 for (position_count_map::const_iterator iter
= pos_counts
.begin ();
702 iter
!= pos_counts
.end (); ++iter
)
703 if (iter
->second
.annotated
)
704 ret
+= iter
->second
.count
;
708 /* Member functions for autofdo_source_profile. */
710 autofdo_source_profile::~autofdo_source_profile ()
712 for (name_function_instance_map::const_iterator iter
= map_
.begin ();
713 iter
!= map_
.end (); ++iter
)
717 /* For a given DECL, returns the top-level function_instance. */
720 autofdo_source_profile::get_function_instance_by_decl (tree decl
) const
722 int index
= afdo_string_table
->get_index_by_decl (decl
);
725 name_function_instance_map::const_iterator ret
= map_
.find (index
);
726 return ret
== map_
.end () ? NULL
: ret
->second
;
729 /* Find count_info for a given gimple STMT. If found, store the count_info
730 in INFO and return true; otherwise return false. */
733 autofdo_source_profile::get_count_info (gimple stmt
, count_info
*info
) const
735 if (LOCATION_LOCUS (gimple_location (stmt
)) == cfun
->function_end_locus
)
739 get_inline_stack (gimple_location (stmt
), &stack
);
740 if (stack
.length () == 0)
742 function_instance
*s
= get_function_instance_by_inline_stack (stack
);
745 return s
->get_count_info (stack
[0].second
, info
);
748 /* Mark LOC as annotated. */
751 autofdo_source_profile::mark_annotated (location_t loc
)
754 get_inline_stack (loc
, &stack
);
755 if (stack
.length () == 0)
757 function_instance
*s
= get_function_instance_by_inline_stack (stack
);
760 s
->mark_annotated (stack
[0].second
);
763 /* Update value profile INFO for STMT from the inlined indirect callsite.
764 Return true if INFO is updated. */
767 autofdo_source_profile::update_inlined_ind_target (gimple stmt
,
770 if (LOCATION_LOCUS (gimple_location (stmt
)) == cfun
->function_end_locus
)
774 get_count_info (stmt
, &old_info
);
776 for (icall_target_map::const_iterator iter
= old_info
.targets
.begin ();
777 iter
!= old_info
.targets
.end (); ++iter
)
778 total
+= iter
->second
;
780 /* Program behavior changed, original promoted (and inlined) target is not
781 hot any more. Will avoid promote the original target.
783 To check if original promoted target is still hot, we check the total
784 count of the unpromoted targets (stored in old_info). If it is no less
785 than half of the callsite count (stored in INFO), the original promoted
786 target is considered not hot any more. */
787 if (total
>= info
->count
/ 2)
791 get_inline_stack (gimple_location (stmt
), &stack
);
792 if (stack
.length () == 0)
794 function_instance
*s
= get_function_instance_by_inline_stack (stack
);
797 icall_target_map map
;
798 if (s
->find_icall_target_map (stmt
, &map
) == 0)
800 for (icall_target_map::const_iterator iter
= map
.begin ();
801 iter
!= map
.end (); ++iter
)
802 info
->targets
[iter
->first
] = iter
->second
;
806 /* Find total count of the callee of EDGE. */
809 autofdo_source_profile::get_callsite_total_count (
810 struct cgraph_edge
*edge
) const
813 stack
.safe_push (std::make_pair (edge
->callee
->decl
, 0));
814 get_inline_stack (gimple_location (edge
->call_stmt
), &stack
);
816 function_instance
*s
= get_function_instance_by_inline_stack (stack
);
818 || afdo_string_table
->get_index (IDENTIFIER_POINTER (
819 DECL_ASSEMBLER_NAME (edge
->callee
->decl
))) != s
->name ())
822 return s
->total_count ();
825 /* Read AutoFDO profile and returns TRUE on success. */
827 /* source profile format:
829 GCOV_TAG_AFDO_FUNCTION: 4 bytes
831 NUM_FUNCTIONS: 4 bytes
835 FUNCTION_INSTANCE_N. */
838 autofdo_source_profile::read ()
840 if (gcov_read_unsigned () != GCOV_TAG_AFDO_FUNCTION
)
842 inform (0, "Not expected TAG.");
846 /* Skip the length of the section. */
847 gcov_read_unsigned ();
849 /* Read in the function/callsite profile, and store it in local
851 unsigned function_num
= gcov_read_unsigned ();
852 for (unsigned i
= 0; i
< function_num
; i
++)
854 function_instance::function_instance_stack stack
;
855 function_instance
*s
= function_instance::read_function_instance (
856 &stack
, gcov_read_counter ());
857 afdo_profile_info
->sum_all
+= s
->total_count ();
858 map_
[s
->name ()] = s
;
863 /* Return the function_instance in the profile that correspond to the
867 autofdo_source_profile::get_function_instance_by_inline_stack (
868 const inline_stack
&stack
) const
870 name_function_instance_map::const_iterator iter
= map_
.find (
871 afdo_string_table
->get_index_by_decl (stack
[stack
.length () - 1].first
));
872 if (iter
== map_
.end())
874 function_instance
*s
= iter
->second
;
875 for (unsigned i
= stack
.length() - 1; i
> 0; i
--)
877 s
= s
->get_function_instance_by_decl (
878 stack
[i
].second
, stack
[i
- 1].first
);
885 /* Module profile is only used by LIPO. Here we simply ignore it. */
888 fake_read_autofdo_module_profile ()
890 /* Read in the module info. */
891 gcov_read_unsigned ();
893 /* Skip the length of the section. */
894 gcov_read_unsigned ();
896 /* Read in the file name table. */
897 unsigned total_module_num
= gcov_read_unsigned ();
898 gcc_assert (total_module_num
== 0);
901 /* Read data from profile data file. */
906 if (gcov_open (auto_profile_file
, 1) == 0)
907 error ("Cannot open profile file %s.", auto_profile_file
);
909 if (gcov_read_unsigned () != GCOV_DATA_MAGIC
)
910 error ("AutoFDO profile magic number does not mathch.");
912 /* Skip the version number. */
913 unsigned version
= gcov_read_unsigned ();
914 if (version
!= AUTO_PROFILE_VERSION
)
915 error ("AutoFDO profile version %u does match %u.",
916 version
, AUTO_PROFILE_VERSION
);
918 /* Skip the empty integer. */
919 gcov_read_unsigned ();
922 afdo_string_table
= new string_table ();
923 if (!afdo_string_table
->read())
924 error ("Cannot read string table from %s.", auto_profile_file
);
926 /* autofdo_source_profile. */
927 afdo_source_profile
= autofdo_source_profile::create ();
928 if (afdo_source_profile
== NULL
)
929 error ("Cannot read function profile from %s.", auto_profile_file
);
931 /* autofdo_module_profile. */
932 fake_read_autofdo_module_profile ();
934 /* Read in the working set. */
935 if (gcov_read_unsigned () != GCOV_TAG_AFDO_WORKING_SET
)
936 error ("Cannot read working set from %s.", auto_profile_file
);
938 /* Skip the length of the section. */
939 gcov_read_unsigned ();
940 gcov_working_set_t set
[128];
941 for (unsigned i
= 0; i
< 128; i
++)
943 set
[i
].num_counters
= gcov_read_unsigned ();
944 set
[i
].min_counter
= gcov_read_counter ();
946 add_working_set (set
);
949 /* From AutoFDO profiles, find values inside STMT for that we want to measure
950 histograms for indirect-call optimization.
952 This function is actually served for 2 purposes:
953 Â Â * before annotation, we need to mark histogram, promote and inline
954 Â Â * after annotation, we just need to mark, and let follow-up logic to
955 Â Â Â decide if it needs to promote and inline. */
958 afdo_indirect_call (gimple_stmt_iterator
*gsi
, const icall_target_map
&map
,
961 gimple stmt
= gsi_stmt (*gsi
);
964 if (map
.size () == 0 || gimple_code (stmt
) != GIMPLE_CALL
965 || 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 promot 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 (gsi
= gsi_start_phis (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
1085 gimple phi
= gsi_stmt (gsi
);
1087 for (i
= 0; i
< gimple_phi_num_args (phi
); i
++)
1088 afdo_source_profile
->mark_annotated (gimple_phi_arg_location (phi
, i
));
1090 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1091 afdo_source_profile
->mark_annotated (e
->goto_locus
);
1093 bb
->count
= max_count
;
1097 /* BB1 and BB2 are in an equivalent class iff:
1098 1. BB1 dominates BB2.
1099 2. BB2 post-dominates BB1.
1100 3. BB1 and BB2 are in the same loop nest.
1101 This function finds the equivalent class for each basic block, and
1102 stores a pointer to the first BB in its equivalent class. Meanwhile,
1103 set bb counts for the same equivalent class to be idenical. Update
1104 ANNOTATED_BB for the first BB in its equivalent class. */
1107 afdo_find_equiv_class (bb_set
*annotated_bb
)
1111 FOR_ALL_BB_FN (bb
, cfun
)
1114 FOR_ALL_BB_FN (bb
, cfun
)
1116 vec
<basic_block
> dom_bbs
;
1120 if (bb
->aux
!= NULL
)
1123 dom_bbs
= get_dominated_by (CDI_DOMINATORS
, bb
);
1124 FOR_EACH_VEC_ELT (dom_bbs
, i
, bb1
)
1125 if (bb1
->aux
== NULL
&& dominated_by_p (CDI_POST_DOMINATORS
, bb
, bb1
)
1126 && bb1
->loop_father
== bb
->loop_father
)
1129 if (bb1
->count
> bb
->count
&& is_bb_annotated (bb1
, *annotated_bb
))
1131 bb
->count
= MAX (bb
->count
, bb1
->count
);
1132 set_bb_annotated (bb
, annotated_bb
);
1135 dom_bbs
= get_dominated_by (CDI_POST_DOMINATORS
, bb
);
1136 FOR_EACH_VEC_ELT (dom_bbs
, i
, bb1
)
1137 if (bb1
->aux
== NULL
&& dominated_by_p (CDI_DOMINATORS
, bb
, bb1
)
1138 && bb1
->loop_father
== bb
->loop_father
)
1141 if (bb1
->count
> bb
->count
&& is_bb_annotated (bb1
, *annotated_bb
))
1143 bb
->count
= MAX (bb
->count
, bb1
->count
);
1144 set_bb_annotated (bb
, annotated_bb
);
1150 /* If a basic block's count is known, and only one of its in/out edges' count
1151 is unknown, its count can be calculated. Meanwhile, if all of the in/out
1152 edges' counts are known, then the basic block's unknown count can also be
1154 IS_SUCC is true if out edges of a basic blocks are examined.
1155 Update ANNOTATED_BB and ANNOTATED_EDGE accordingly.
1156 Return TRUE if any basic block/edge count is changed. */
1159 afdo_propagate_edge (bool is_succ
, bb_set
*annotated_bb
,
1160 edge_set
*annotated_edge
)
1163 bool changed
= false;
1165 FOR_EACH_BB_FN (bb
, cfun
)
1167 edge e
, unknown_edge
= NULL
;
1169 int num_unknown_edge
= 0;
1170 gcov_type total_known_count
= 0;
1172 FOR_EACH_EDGE (e
, ei
, is_succ
? bb
->succs
: bb
->preds
)
1173 if (!is_edge_annotated (e
, *annotated_edge
))
1174 num_unknown_edge
++, unknown_edge
= e
;
1176 total_known_count
+= e
->count
;
1178 if (num_unknown_edge
== 0)
1180 if (total_known_count
> bb
->count
)
1182 bb
->count
= total_known_count
;
1185 if (!is_bb_annotated (bb
, *annotated_bb
))
1187 set_bb_annotated (bb
, annotated_bb
);
1191 else if (num_unknown_edge
== 1 && is_bb_annotated (bb
, *annotated_bb
))
1193 if (bb
->count
>= total_known_count
)
1194 unknown_edge
->count
= bb
->count
- total_known_count
;
1196 unknown_edge
->count
= 0;
1197 set_edge_annotated (unknown_edge
, annotated_edge
);
1204 /* Special propagation for circuit expressions. Because GCC translates
1205 control flow into data flow for circuit expressions. E.g.
1212 will be translated into:
1227 tmp = PHI (0 (BB1), 0 (BB.t1), 1 (BB.t2)
1233 In this case, we need to propagate through PHI to determine the edge
1234 count of BB1->BB.t1, BB.t1->BB.t2.
1235 Update ANNOTATED_EDGE accordingly. */
1238 afdo_propagate_circuit (const bb_set
&annotated_bb
, edge_set
*annotated_edge
)
1241 FOR_ALL_BB_FN (bb
, cfun
)
1244 tree cmp_rhs
, cmp_lhs
;
1245 gimple cmp_stmt
= last_stmt (bb
);
1249 if (!cmp_stmt
|| gimple_code (cmp_stmt
) != GIMPLE_COND
)
1251 cmp_rhs
= gimple_cond_rhs (cmp_stmt
);
1252 cmp_lhs
= gimple_cond_lhs (cmp_stmt
);
1253 if (!TREE_CONSTANT (cmp_rhs
)
1254 || !(integer_zerop (cmp_rhs
) || integer_onep (cmp_rhs
)))
1256 if (TREE_CODE (cmp_lhs
) != SSA_NAME
)
1258 if (!is_bb_annotated (bb
, annotated_bb
))
1260 phi_stmt
= SSA_NAME_DEF_STMT (cmp_lhs
);
1261 while (phi_stmt
&& gimple_code (phi_stmt
) == GIMPLE_ASSIGN
1262 && gimple_assign_single_p (phi_stmt
)
1263 && TREE_CODE (gimple_assign_rhs1 (phi_stmt
)) == SSA_NAME
)
1264 phi_stmt
= SSA_NAME_DEF_STMT (gimple_assign_rhs1 (phi_stmt
));
1265 if (!phi_stmt
|| gimple_code (phi_stmt
) != GIMPLE_PHI
)
1267 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1269 unsigned i
, total
= 0;
1271 bool check_value_one
= (((integer_onep (cmp_rhs
))
1272 ^ (gimple_cond_code (cmp_stmt
) == EQ_EXPR
))
1273 ^ ((e
->flags
& EDGE_TRUE_VALUE
) != 0));
1274 if (!is_edge_annotated (e
, *annotated_edge
))
1276 for (i
= 0; i
< gimple_phi_num_args (phi_stmt
); i
++)
1278 tree val
= gimple_phi_arg_def (phi_stmt
, i
);
1279 edge ep
= gimple_phi_arg_edge (phi_stmt
, i
);
1281 if (!TREE_CONSTANT (val
)
1282 || !(integer_zerop (val
) || integer_onep (val
)))
1284 if (check_value_one
^ integer_onep (val
))
1288 if (e
->probability
== 0 && !is_edge_annotated (ep
, *annotated_edge
))
1290 ep
->probability
= 0;
1292 set_edge_annotated (ep
, annotated_edge
);
1295 if (total
== 1 && !is_edge_annotated (only_one
, *annotated_edge
))
1297 only_one
->probability
= e
->probability
;
1298 only_one
->count
= e
->count
;
1299 set_edge_annotated (only_one
, annotated_edge
);
1305 /* Propagate the basic block count and edge count on the control flow
1306 graph. We do the propagation iteratively until stablize. */
1309 afdo_propagate (bb_set
*annotated_bb
, edge_set
*annotated_edge
)
1312 bool changed
= true;
1315 FOR_ALL_BB_FN (bb
, cfun
)
1317 bb
->count
= ((basic_block
)bb
->aux
)->count
;
1318 if (is_bb_annotated ((const basic_block
)bb
->aux
, *annotated_bb
))
1319 set_bb_annotated (bb
, annotated_bb
);
1322 while (changed
&& i
++ < 10)
1326 if (afdo_propagate_edge (true, annotated_bb
, annotated_edge
))
1328 if (afdo_propagate_edge (false, annotated_bb
, annotated_edge
))
1330 afdo_propagate_circuit (*annotated_bb
, annotated_edge
);
1334 /* Propagate counts on control flow graph and calculate branch
1338 afdo_calculate_branch_prob (bb_set
*annotated_bb
, edge_set
*annotated_edge
)
1341 bool has_sample
= false;
1343 FOR_EACH_BB_FN (bb
, cfun
)
1350 calculate_dominance_info (CDI_POST_DOMINATORS
);
1351 calculate_dominance_info (CDI_DOMINATORS
);
1352 loop_optimizer_init (0);
1354 afdo_find_equiv_class (annotated_bb
);
1355 afdo_propagate (annotated_bb
, annotated_edge
);
1357 FOR_EACH_BB_FN (bb
, cfun
)
1361 int num_unknown_succ
= 0;
1362 gcov_type total_count
= 0;
1364 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1366 if (!is_edge_annotated (e
, *annotated_edge
))
1369 total_count
+= e
->count
;
1371 if (num_unknown_succ
== 0 && total_count
> 0)
1373 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1374 e
->probability
= (double)e
->count
* REG_BR_PROB_BASE
/ total_count
;
1377 FOR_ALL_BB_FN (bb
, cfun
)
1382 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1383 e
->count
= (double)bb
->count
* e
->probability
/ REG_BR_PROB_BASE
;
1387 loop_optimizer_finalize ();
1388 free_dominance_info (CDI_DOMINATORS
);
1389 free_dominance_info (CDI_POST_DOMINATORS
);
1392 /* Perform value profile transformation using AutoFDO profile. Add the
1393 promoted stmts to PROMOTED_STMTS. Return TRUE if there is any
1394 indirect call promoted. */
1397 afdo_vpt_for_early_inline (stmt_set
*promoted_stmts
)
1400 if (afdo_source_profile
->get_function_instance_by_decl (
1401 current_function_decl
) == NULL
)
1404 compute_inline_parameters (cgraph_node::get (current_function_decl
), true);
1406 bool has_vpt
= false;
1407 FOR_EACH_BB_FN (bb
, cfun
)
1409 if (!has_indirect_call (bb
))
1411 gimple_stmt_iterator gsi
;
1413 gcov_type bb_count
= 0;
1414 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
1417 gimple stmt
= gsi_stmt (gsi
);
1418 if (afdo_source_profile
->get_count_info (stmt
, &info
))
1419 bb_count
= MAX (bb_count
, info
.count
);
1422 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
1424 gimple stmt
= gsi_stmt (gsi
);
1425 /* IC_promotion and early_inline_2 is done in multiple iterations.
1426 No need to promoted the stmt if its in promoted_stmts (means
1427 it is already been promoted in the previous iterations). */
1428 if (gimple_code (stmt
) != GIMPLE_CALL
|| gimple_call_fn (stmt
) == NULL
1429 || TREE_CODE (gimple_call_fn (stmt
)) == FUNCTION_DECL
1430 || promoted_stmts
->find (stmt
) != promoted_stmts
->end ())
1434 afdo_source_profile
->get_count_info (stmt
, &info
);
1435 info
.count
= bb_count
;
1436 if (afdo_source_profile
->update_inlined_ind_target (stmt
, &info
))
1438 /* Promote the indirect call and update the promoted_stmts. */
1439 promoted_stmts
->insert (stmt
);
1440 afdo_vpt (&gsi
, info
.targets
, true);
1447 optimize_inline_calls (current_function_decl
);
1454 /* Annotate auto profile to the control flow graph. Do not annotate value
1455 profile for stmts in PROMOTED_STMTS. */
1458 afdo_annotate_cfg (const stmt_set
&promoted_stmts
)
1461 bb_set annotated_bb
;
1462 edge_set annotated_edge
;
1463 const function_instance
*s
1464 = afdo_source_profile
->get_function_instance_by_decl (
1465 current_function_decl
);
1469 cgraph_node::get (current_function_decl
)->count
= s
->head_count ();
1470 ENTRY_BLOCK_PTR_FOR_FN (cfun
)->count
= s
->head_count ();
1471 gcov_type max_count
= ENTRY_BLOCK_PTR_FOR_FN (cfun
)->count
;
1473 FOR_EACH_BB_FN (bb
, cfun
)
1479 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1482 if (afdo_set_bb_count (bb
, promoted_stmts
))
1483 set_bb_annotated (bb
, &annotated_bb
);
1484 if (bb
->count
> max_count
)
1485 max_count
= bb
->count
;
1487 if (ENTRY_BLOCK_PTR_FOR_FN (cfun
)->count
1488 > ENTRY_BLOCK_PTR_FOR_FN (cfun
)->next_bb
->count
)
1490 ENTRY_BLOCK_PTR_FOR_FN (cfun
)->next_bb
->count
1491 = ENTRY_BLOCK_PTR_FOR_FN (cfun
)->count
;
1492 set_bb_annotated (ENTRY_BLOCK_PTR_FOR_FN (cfun
)->next_bb
, &annotated_bb
);
1494 if (ENTRY_BLOCK_PTR_FOR_FN (cfun
)->count
1495 > EXIT_BLOCK_PTR_FOR_FN (cfun
)->prev_bb
->count
)
1497 EXIT_BLOCK_PTR_FOR_FN (cfun
)->prev_bb
->count
1498 = ENTRY_BLOCK_PTR_FOR_FN (cfun
)->count
;
1499 set_bb_annotated (EXIT_BLOCK_PTR_FOR_FN (cfun
)->prev_bb
, &annotated_bb
);
1501 afdo_source_profile
->mark_annotated (
1502 DECL_SOURCE_LOCATION (current_function_decl
));
1503 afdo_source_profile
->mark_annotated (cfun
->function_start_locus
);
1504 afdo_source_profile
->mark_annotated (cfun
->function_end_locus
);
1507 afdo_calculate_branch_prob (&annotated_bb
, &annotated_edge
);
1509 profile_status_for_fn (cfun
) = PROFILE_READ
;
1511 if (flag_value_profile_transformations
)
1512 gimple_value_profile_transformations ();
1515 /* Wrapper function to invoke early inliner. */
1520 compute_inline_parameters (cgraph_node::get (current_function_decl
), true);
1521 unsigned todo
= early_inliner (cfun
);
1522 if (todo
& TODO_update_ssa_any
)
1523 update_ssa (TODO_update_ssa
);
1526 /* Use AutoFDO profile to annoate the control flow graph.
1527 Return the todo flag. */
1532 struct cgraph_node
*node
;
1534 if (symtab
->state
== FINISHED
)
1537 init_node_map (true);
1538 profile_info
= autofdo::afdo_profile_info
;
1540 FOR_EACH_FUNCTION (node
)
1542 if (!gimple_has_body_p (node
->decl
))
1545 /* Don't profile functions produced for builtin stuff. */
1546 if (DECL_SOURCE_LOCATION (node
->decl
) == BUILTINS_LOCATION
)
1549 push_cfun (DECL_STRUCT_FUNCTION (node
->decl
));
1551 /* First do indirect call promotion and early inline to make the
1552 IR match the profiled binary before actual annotation.
1554 This is needed because an indirect call might have been promoted
1555 and inlined in the profiled binary. If we do not promote and
1556 inline these indirect calls before annotation, the profile for
1557 these promoted functions will be lost.
1559 e.g. foo() --indirect_call--> bar()
1560 In profiled binary, the callsite is promoted and inlined, making
1561 the profile look like:
1571 Before AutoFDO pass, loc_foo_2 is not promoted thus not inlined.
1572 If we perform annotation on it, the profile inside bar@loc_foo2
1575 To avoid this, we promote loc_foo_2 and inline the promoted bar
1576 function before annotation, so the profile inside bar@loc_foo2
1578 autofdo::stmt_set promoted_stmts
;
1579 for (int i
= 0; i
< PARAM_VALUE (PARAM_EARLY_INLINER_MAX_ITERATIONS
); i
++)
1581 if (!flag_value_profile_transformations
1582 || !autofdo::afdo_vpt_for_early_inline (&promoted_stmts
))
1588 autofdo::afdo_annotate_cfg (promoted_stmts
);
1589 compute_function_frequency ();
1590 update_ssa (TODO_update_ssa
);
1592 /* Local pure-const may imply need to fixup the cfg. */
1593 if (execute_fixup_cfg () & TODO_cleanup_cfg
)
1594 cleanup_tree_cfg ();
1596 free_dominance_info (CDI_DOMINATORS
);
1597 free_dominance_info (CDI_POST_DOMINATORS
);
1598 cgraph_edge::rebuild_edges ();
1602 return TODO_rebuild_cgraph_edges
;
1604 } /* namespace autofdo. */
1606 /* Read the profile from the profile data file. */
1609 read_autofdo_file (void)
1611 if (auto_profile_file
== NULL
)
1612 auto_profile_file
= DEFAULT_AUTO_PROFILE_FILE
;
1614 autofdo::afdo_profile_info
= (struct gcov_ctr_summary
*)xcalloc (
1615 1, sizeof (struct gcov_ctr_summary
));
1616 autofdo::afdo_profile_info
->runs
= 1;
1617 autofdo::afdo_profile_info
->sum_max
= 0;
1618 autofdo::afdo_profile_info
->sum_all
= 0;
1620 /* Read the profile from the profile file. */
1621 autofdo::read_profile ();
1624 /* Free the resources. */
1627 end_auto_profile (void)
1629 delete autofdo::afdo_source_profile
;
1630 delete autofdo::afdo_string_table
;
1631 profile_info
= NULL
;
1634 /* Returns TRUE if EDGE is hot enough to be inlined early. */
1637 afdo_callsite_hot_enough_for_early_inline (struct cgraph_edge
*edge
)
1640 = autofdo::afdo_source_profile
->get_callsite_total_count (edge
);
1644 const struct gcov_ctr_summary
*saved_profile_info
= profile_info
;
1645 /* At earling inline stage, profile_info is not set yet. We need to
1646 temporarily set it to afdo_profile_info to calculate hotness. */
1647 profile_info
= autofdo::afdo_profile_info
;
1648 is_hot
= maybe_hot_count_p (NULL
, count
);
1649 profile_info
= saved_profile_info
;
1659 const pass_data pass_data_ipa_auto_profile
= {
1660 SIMPLE_IPA_PASS
, "afdo", /* name */
1661 OPTGROUP_NONE
, /* optinfo_flags */
1662 TV_IPA_AUTOFDO
, /* tv_id */
1663 0, /* properties_required */
1664 0, /* properties_provided */
1665 0, /* properties_destroyed */
1666 0, /* todo_flags_start */
1667 0, /* todo_flags_finish */
1670 class pass_ipa_auto_profile
: public simple_ipa_opt_pass
1673 pass_ipa_auto_profile (gcc::context
*ctxt
)
1674 : simple_ipa_opt_pass (pass_data_ipa_auto_profile
, ctxt
)
1678 /* opt_pass methods: */
1682 return flag_auto_profile
;
1684 virtual unsigned int
1685 execute (function
*)
1687 return autofdo::auto_profile ();
1689 }; // class pass_ipa_auto_profile
1693 simple_ipa_opt_pass
*
1694 make_pass_ipa_auto_profile (gcc::context
*ctxt
)
1696 return new pass_ipa_auto_profile (ctxt
);