From: Dhruv Chawla <dhr...@nvidia.com> This patch modifies afdo_set_bb_count to propagate profile information to outline copies of functions if they are not inlined. This information gets lost otherwise.
Signed-off-by: Dhruv Chawla <dhr...@nvidia.com> gcc/ChangeLog: * gcc/auto-profile.cc (count_info): Adjust comments. (function_instance::in_afdo_source_profile): New function. (function_instance::set_in_afdo_source_profile): Likewise. (function_instance::get_callsites): Likewise. (autofdo_source_profile::add_function_instance): Likewise. (function_instance::in_afdo_source_profile_): New member. (autofdo_source_profile::~autofdo_source_profile): Use in_afdo_source_profile to prevent a double-free bug. (afdo_set_bb_count): Propagate inline information to non-inlined outline copy. --- gcc/auto-profile.cc | 72 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/gcc/auto-profile.cc b/gcc/auto-profile.cc index e12b3048f20..228b65601d1 100644 --- a/gcc/auto-profile.cc +++ b/gcc/auto-profile.cc @@ -138,7 +138,7 @@ typedef std::map<unsigned, gcov_type> icall_target_map; to direct call. */ typedef std::set<gimple *> stmt_set; -/* Represent count info of an inline stack. */ +/* Represent count info of a source position. */ class count_info { public: @@ -147,12 +147,6 @@ public: /* Map from indirect call target to its sample count. */ icall_target_map targets; - - /* Whether this inline stack is already used in annotation. - - Each inline stack should only be used to annotate IR once. - This will be enforced when instruction-level discriminator - is supported. */ }; /* operator< for "const char *". */ @@ -230,6 +224,10 @@ public: return head_count_; } + bool in_afdo_source_profile () const { return in_afdo_source_profile_; } + + void set_in_afdo_source_profile () { in_afdo_source_profile_ = true; } + /* Traverse callsites of the current function_instance to find one at the location of LINENO and callee name represented in DECL. */ function_instance *get_function_instance_by_decl (unsigned lineno, @@ -258,7 +256,8 @@ private: typedef std::map<callsite, function_instance *> callsite_map; function_instance (unsigned name, gcov_type head_count) - : name_ (name), total_count_ (0), head_count_ (head_count) + : name_ (name), total_count_ (0), head_count_ (head_count), + in_afdo_source_profile_ (false) { } @@ -279,6 +278,13 @@ private: /* Map from source location to count_info. */ position_count_map pos_counts; + + /* If this is an inline instance tracked in afdo_source_profile. */ + bool in_afdo_source_profile_; + +public: + /* Get the callsite map for the function_instance. */ + const callsite_map &get_callsites () const { return callsites; } }; /* Profile for all functions. */ @@ -316,6 +322,10 @@ public: Return true if INFO is updated. */ bool update_inlined_ind_target (gcall *stmt, count_info *info); + /* Add a new function_instance entry if an inlined function is found in the + profile that doesn't have a corresponding entry in the map. */ + bool add_function_instance (function_instance *fun); + private: /* Map from function_instance name index (in string_table) to function_instance. */ @@ -700,7 +710,8 @@ autofdo_source_profile::~autofdo_source_profile () { for (name_function_instance_map::const_iterator iter = map_.begin (); iter != map_.end (); ++iter) - delete iter->second; + if (!iter->second->in_afdo_source_profile ()) + delete iter->second; } /* For a given DECL, returns the top-level function_instance. */ @@ -814,6 +825,24 @@ autofdo_source_profile::update_inlined_ind_target (gcall *stmt, return true; } +/* Add a new function_instance entry if an inlined function is found in the + profile that doesn't have a corresponding entry in the map. Return false if + the function_instance already exists, true if it doesn't. */ + +bool +autofdo_source_profile::add_function_instance (function_instance *fun) +{ + int name = fun->name (); + if (auto fun_it = map_.find (name); fun_it != map_.end ()) + { + fun_it->second->merge (fun); + return false; + } + + map_[name] = fun; + return true; +} + /* Find total count of the callee of EDGE. */ gcov_type @@ -1144,6 +1173,31 @@ afdo_set_bb_count (basic_block bb, const stmt_set &promoted) gimple *stmt = gsi_stmt (gsi); if (gimple_clobber_p (stmt) || is_gimple_debug (stmt)) continue; + if (gimple_code (stmt) == GIMPLE_CALL) + { + tree fn = gimple_call_fndecl (stmt); + function_instance *cur + = afdo_source_profile->get_function_instance_by_decl ( + current_function_decl); + if (!cur || !fn) + continue; + + int name = afdo_string_table->get_index_by_decl (fn); + unsigned current_offset = get_relative_location_for_stmt (stmt); + auto it = cur->get_callsites ().find ( + std::make_pair (current_offset, name)); + if (it == cur->get_callsites ().end ()) + continue; + + /* There exists an inlined callsite in the binary that has not + been inlined in the current callgraph. */ + bool ins = afdo_source_profile->add_function_instance (it->second); + /* This prevents a double-free bug. */ + if (ins) + it->second->set_in_afdo_source_profile (); + + continue; + } if (afdo_source_profile->get_count_info (stmt, &info)) { if (info.count > max_count) -- 2.44.0