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

Reply via email to