From: Dhruv Chawla <dhr...@nvidia.com> This patch modifies the auto-profile pass to read file names from GCOV. A function is only annotated with a set of profile counts if its file name matches the file name that the function in the GCOV file was recorded with. It also bumps the GCOV version to 3 as the file format has changed.
gcc/ChangeLog: * auto-profile.cc (AUTO_PROFILE_VERSION): Bump from 2 to 3. (string_table::get_real_name): Define new member function. (string_table::get_file_name): Likewise. (string_table::get_file_name_idx): Likewise. (string_table::real_names_): Define new class member. (string_table::file_names_): Likewise. (string_table::file_map_): Likewise. (string_table::name_instance_map): Update to be a 2-dimensional map from function name to file name to function_instance *. (string_table::~string_table): Deallocate from real_names_ and file_names_ as well. (string_table::read): Read file name header from GCOV file. (autofdo_source_profile::~autofdo_source_profile): Deallocate from nested map. (autofdo_source_profile::read): Use file name when storing entry into map_. (autofdo_source_profile::get_function_instance_by_decl): Use DECL_SOURCE_FILE for function_instance lookup. (autofdo_source_profile::get_function_instance_by_inline_stack): Likewise. --- gcc/auto-profile.cc | 101 ++++++++++++++++++++++++++++++---- gcc/testsuite/lib/profopt.exp | 2 +- 2 files changed, 91 insertions(+), 12 deletions(-) diff --git a/gcc/auto-profile.cc b/gcc/auto-profile.cc index e12b3048f20..de186598d43 100644 --- a/gcc/auto-profile.cc +++ b/gcc/auto-profile.cc @@ -99,7 +99,7 @@ along with GCC; see the file COPYING3. If not see */ #define DEFAULT_AUTO_PROFILE_FILE "fbdata.afdo" -#define AUTO_PROFILE_VERSION 2 +#define AUTO_PROFILE_VERSION 3 namespace autofdo { @@ -182,13 +182,25 @@ public: /* For a given index, returns the string. */ const char *get_name (int index) const; + /* For a given index, get the name without the suffix stripped from it. */ + const char *get_real_name (int index) const; + + /* For a given suffixed function name, get the source file name if known. */ + const char *get_file_name (const char *real_name) const; + + /* Get the file name from the function name index. */ + const char *get_file_name_idx (int index) const; + /* Read profile, return TRUE on success. */ bool read (); private: typedef std::map<const char *, unsigned, string_compare> string_index_map; string_vector vector_; + string_vector real_names_; + string_vector file_names_; string_index_map map_; + string_index_map file_map_; }; /* Profile of a function instance: @@ -318,8 +330,10 @@ public: private: /* Map from function_instance name index (in string_table) to - function_instance. */ - typedef std::map<unsigned, function_instance *> name_function_instance_map; + map from source file name to function_instance. */ + typedef std::map<unsigned, + std::map<const char *, function_instance *, string_compare>> + name_function_instance_map; autofdo_source_profile () {} @@ -457,7 +471,12 @@ has_indirect_call (basic_block bb) string_table::~string_table () { for (unsigned i = 0; i < vector_.length (); i++) - free (vector_[i]); + { + free (vector_[i]); + free (real_names_[i]); + } + for (unsigned i = 0; i < file_names_.length (); i++) + free (file_names_[i]); } @@ -506,6 +525,34 @@ string_table::get_name (int index) const return vector_[index]; } +/* For a given index, get the name without the suffix stripped from it. */ + +const char * +string_table::get_real_name (int index) const +{ + gcc_assert (index > 0 && index < (int) real_names_.length ()); + return real_names_[index]; +} + +/* For a given suffixed function name, get the source file name if known. */ + +const char * +string_table::get_file_name (const char *real_name) const +{ + auto it = file_map_.find (real_name); + if (it != file_map_.end () && it->second < file_names_.length ()) + return file_names_[it->second]; + else + return "<unknown>"; +} + +/* Get the file name from the function name index. */ +const char * +string_table::get_file_name_idx (int index) const +{ + return get_file_name (get_real_name (index)); +} + /* Read the string table. Return TRUE if reading is successful. */ bool @@ -515,12 +562,21 @@ string_table::read () return false; /* Skip the length of the section. */ gcov_read_unsigned (); + /* Read in the file names. */ + unsigned file_num = gcov_read_unsigned (); + for (unsigned i = 0; i < file_num; i++) + file_names_.safe_push (const_cast<char *> (gcov_read_string ())); /* Read in the file name table. */ unsigned string_num = gcov_read_unsigned (); for (unsigned i = 0; i < string_num; i++) { - vector_.safe_push (get_original_name (gcov_read_string ())); + char *string = const_cast<char *> (gcov_read_string ()); + unsigned file_index = gcov_read_unsigned (); + vector_.safe_push (get_original_name (string)); + real_names_.safe_push (xstrdup (string)); map_[vector_.last ()] = i; + file_map_[real_names_.last ()] = file_index; + free (string); } return true; } @@ -572,6 +628,12 @@ void function_instance::merge (function_instance *other) total_count_ += other->total_count_; head_count_ += other->head_count_; + const char *this_file = afdo_string_table->get_file_name_idx (name ()); + const char *other_file + = afdo_string_table->get_file_name_idx (other->name ()); + if (strcmp (this_file, other_file) != 0) + return; + for (callsite_map::const_iterator iter = other->callsites.begin (); iter != other->callsites.end (); ++iter) if (callsites.count (iter->first) == 0) @@ -700,7 +762,8 @@ autofdo_source_profile::~autofdo_source_profile () { for (name_function_instance_map::const_iterator iter = map_.begin (); iter != map_.end (); ++iter) - delete iter->second; + for (auto it = iter->second.begin (); it != iter->second.end (); it++) + delete it->second; } /* For a given DECL, returns the top-level function_instance. */ @@ -712,7 +775,14 @@ autofdo_source_profile::get_function_instance_by_decl (tree decl) const if (index == -1) return NULL; name_function_instance_map::const_iterator ret = map_.find (index); - return ret == map_.end () ? NULL : ret->second; + if (ret != map_.end ()) + { + const char *file = DECL_SOURCE_FILE (decl); + auto instance = ret->second.find (file); + return instance == ret->second.end () ? NULL : instance->second; + } + + return NULL; } /* Find count_info for a given gimple STMT. If found, store the count_info @@ -870,10 +940,13 @@ autofdo_source_profile::read () &stack, gcov_read_counter ()); int fun_id = afdo_string_table->get_index (afdo_string_table->get_name (s->name ())); + const char *real_name = afdo_string_table->get_real_name (s->name ()); + const char *file_name = afdo_string_table->get_file_name (real_name); + /* If function_instace with get_original_name (without the clone suffix) exixts, merge the function instances. */ - if (map_.count (fun_id) == 0) - map_[fun_id] = s; + if (map_.count (fun_id) == 0 || map_[fun_id].count (file_name) == 0) + map_[fun_id][file_name] = s; else { /* Since this is invoked very early, before the pass @@ -886,7 +959,7 @@ autofdo_source_profile::read () dump_printf_loc (MSG_NOTE, loc, "Merging profile for %s\n", afdo_string_table->get_name (s->name ())); } - map_[fun_id]->merge (s); + map_[fun_id][file_name]->merge (s); } } g->get_dumps ()->dump_finish (profile_pass_num); @@ -904,7 +977,13 @@ autofdo_source_profile::get_function_instance_by_inline_stack ( afdo_string_table->get_index_by_decl (stack[stack.length () - 1].first)); if (iter == map_.end()) return NULL; - function_instance *s = iter->second; + + const char *file_name = DECL_SOURCE_FILE (stack[stack.length () - 1].first); + auto it = iter->second.find (file_name); + if (it == iter->second.end ()) + return NULL; + + function_instance *s = it->second; for (unsigned i = stack.length() - 1; i > 0; i--) { s = s->get_function_instance_by_decl ( diff --git a/gcc/testsuite/lib/profopt.exp b/gcc/testsuite/lib/profopt.exp index b4d244b3132..8f0d0c5c554 100644 --- a/gcc/testsuite/lib/profopt.exp +++ b/gcc/testsuite/lib/profopt.exp @@ -451,7 +451,7 @@ proc profopt-execute { src } { # convert profile if { $run_autofdo == 1 } { set bprefix "afdo." - set cmd "create_gcov --binary $execname1 --profile=$tmpdir/$base.perf.data -gcov_version=2 --gcov=$tmpdir/$bprefix$base.$ext" + set cmd "create_gcov --binary $execname1 --profile=$tmpdir/$base.perf.data --gcov_version=3 --gcov=$tmpdir/$bprefix$base.$ext" verbose "Running $cmd" set id [remote_spawn "" $cmd] if { $id < 0 } { -- 2.44.0