From: Dhruv Chawla <[email protected]>

Signed-off-by: Dhruv Chawla <[email protected]>

gcc/ChangeLog:

        * auto-profile.cc (AUTO_PROFILE_VERSION): Bump to 3.
        (get_normalized_path): New function.
        (string_table::~string_table): Update to free filenames.
        (string_table::vector_): Rename to ...
        (string_table::symbol_names_): ... this.
        (string_table::map_): Rename to ...
        (string_table::symbol_name_map_): ... this.
        (string_table::filenames_): New member.
        (string_table::filename_map_): Likewise.
        (string_table::symbol_to_filename_map_): Likewise.
        (string_table::get_index): Update to lookup symbol_name_map_.
        (string_table::get_name): Rename to ...
        (string_table::get_symbol_name): ... this.
        (string_table::add_name): Rename to ...
        (string_table::add_symbol_name): ... this.
        (string_table::get_filename): New function.
        (string_table::get_filename_by_symbol): Likewise.
        (string_table::get_filename_index): Likewise.
        (string_table::add_filename): Likewise.
        (string_table::read): Read file names from the GCOV profile.
        (function_instance::offline): Call
        get_function_instance_by_descriptor.
        (string_table::get_cgraph_node): Call get_symbol_name and
        symbol_name.
        (function_instance::get_function_instance_by_decl): Likewise.
        (function_instance::get_cgraph_node): Likewise.
        (function_instance::merge): Likewise.
        (match_with_target): Likewise.
        (function_instance::match): Likewise.
        (function_instance::dump): Likewise.
        (function_instance::dump_inline_stack): Likewise.
        (function_instance::find_icall_target_map): Likewise.
        (autofdo_source_profile::offline_unrealized_inlines): Likewise.
        (autofdo_source_profile::offline_external_functions): Likewise.
        (function_instance::read_function_instance): Likewise.
        (afdo_indirect_call):
        Also call find_function_instance, add_function_instance and
        remove_function_instance.
        (autofdo_source_profile::read): Likewise.
        (autofdo_source_profile::get_function_instance_by_decl): Call
        find_function_instance.
        (autofdo_source_profile::get_function_instance_by_name_index):
        Rename to ...
        (autofdo_source_profile::get_function_instance_by_descriptor):
        ... this.
        (autofdo_source_profile::find_iter_for_function_instance): New
        function.
        (autofdo_source_profile::find_function_instance): Likewise.
        (autofdo_source_profile::add_function_instance): Likewise.
        (autofdo_source_profile::remove_function_instance): Likewise.
---
 gcc/auto-profile.cc | 577 +++++++++++++++++++++++++++++++-------------
 1 file changed, 404 insertions(+), 173 deletions(-)

diff --git a/gcc/auto-profile.cc b/gcc/auto-profile.cc
index cf7a2191336..5e62c7f6b59 100644
--- a/gcc/auto-profile.cc
+++ b/gcc/auto-profile.cc
@@ -122,7 +122,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
 
 /* profile counts determined by AFDO smaller than afdo_hot_bb_threshold are
    considered cols.  */
@@ -188,7 +188,7 @@ struct decl_lineno
 typedef auto_vec<decl_lineno, 20> inline_stack;
 
 /* String array that stores function names.  */
-typedef auto_vec<char *> string_vector;
+typedef auto_vec<const char *> string_vector;
 
 /* Map from function name's index in string_table to target's
    execution count.  */
@@ -232,6 +232,8 @@ struct string_compare
 class string_table
 {
 public:
+  static const int unknown_filename = -1;
+
   string_table ()
   {}
 
@@ -243,27 +245,49 @@ public:
   /* For a given decl, returns the index of the decl name.  */
   int get_index_by_decl (tree decl) const;
 
-  /* For a given index, returns the string.  */
-  const char *get_name (int index) const;
+  /* For a given index, returns the symbol name.  */
+  const char *get_symbol_name (int index) const;
+
+  /* For a given index, returns the filename.  */
+  const char *get_filename (int index) const;
+
+  /* For a given symbol name index, returns the filename index.  */
+  int get_filename_by_symbol (int index) const;
+
+  /* For a given function name, returns the filename index.  */
+  int get_filename_by_symbol (const char *name) const;
+
+  /* For a given filename, returns the index.  */
+  int get_filename_index (const char *name) const;
 
   /* Read profile, return TRUE on success.  */
   bool read ();
 
   /* Return number of entries.  */
-  size_t num_entries ()
-  {
-    return vector_.length ();
-  }
+  size_t num_entries () { return symbol_names_.length (); }
+
+  /* Add new symbol name STRING (with an associated file name FILENAME_IDX) and
+     return its index.  */
+  int add_symbol_name (const char *string, int filename_idx);
 
-  /* Add new name and return its index.  */
-  int add_name (char *);
+  /* Add new filename and return its index (returning the same if it already
+   * exists).  */
+  int add_filename (const char *name);
 
   /* Return cgraph node corresponding to given name index.  */
   cgraph_node *get_cgraph_node (int);
 private:
   typedef std::map<const char *, unsigned, string_compare> string_index_map;
-  string_vector vector_;
-  string_index_map map_;
+  typedef std::map<const char *, auto_vec<unsigned>, string_compare>
+    clashing_name_map;
+  typedef std::map<const char *, char *, string_compare> string_string_map;
+
+  string_vector symbol_names_;
+  string_vector filenames_;
+
+  string_index_map symbol_name_map_;
+  string_index_map filename_map_;
+  string_index_map symbol_to_filename_map_;
 };
 
 /* Profile of a function instance:
@@ -276,6 +300,38 @@ private:
 class function_instance
 {
 public:
+  class descriptor
+  {
+    /* The string_table index for the file name.  */
+    unsigned file_name_;
+    /* The string_table index for the function name.  */
+    unsigned symbol_name_;
+
+  public:
+    unsigned file_name () const { return file_name_; }
+    unsigned symbol_name () const { return symbol_name_; }
+
+    descriptor (unsigned file_name, unsigned symbol_name)
+      : file_name_ (file_name), symbol_name_ (symbol_name)
+    {}
+
+    descriptor (int file_name, int symbol_name)
+      : file_name_ (file_name), symbol_name_ (symbol_name)
+    {}
+
+    unsigned set_symbol_name (unsigned new_name)
+    {
+      return symbol_name_ = new_name;
+    }
+
+    bool operator< (const descriptor &other) const
+    {
+      return file_name_ < other.file_name_
+            || (file_name_ == other.file_name_
+                && symbol_name_ < other.symbol_name_);
+    }
+  };
+
   typedef auto_vec<function_instance *> function_instance_stack;
 
   /* Read the profile and return a function_instance with head count as
@@ -289,16 +345,14 @@ public:
   ~function_instance ();
 
   /* Accessors.  */
-  int
-  name () const
+  int symbol_name () const { return descriptor_.symbol_name (); }
+  int file_name () const { return descriptor_.file_name (); }
+  int set_symbol_name (int index)
   {
-    return name_;
-  }
-  int
-  set_name (int index)
-  {
-    return name_ = index;
+    return descriptor_.set_symbol_name (index);
   }
+  descriptor get_descriptor () const { return descriptor_; }
+
   gcov_type
   total_count () const
   {
@@ -472,10 +526,11 @@ private:
   /* Map from callsite to callee function_instance.  */
   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),
-      removed_icall_target_ (false), realized_ (false),
-      in_worklist_ (false), inlined_to_ (NULL),
+  function_instance (unsigned symbol_name, unsigned file_name,
+                    gcov_type head_count)
+    : descriptor_ (file_name, symbol_name), total_count_ (0),
+      head_count_ (head_count), removed_icall_target_ (false),
+      realized_ (false), in_worklist_ (false), inlined_to_ (NULL),
       location_ (UNKNOWN_LOCATION), call_location_ (UNKNOWN_LOCATION)
   {
   }
@@ -483,8 +538,8 @@ private:
   /* Map from source location (decl_lineno) to profile (count_info).  */
   typedef std::map<unsigned, count_info> position_count_map;
 
-  /* function_instance name index in the string_table.  */
-  unsigned name_;
+  /* The indices into the string table identifying the function_instance.  */
+  descriptor descriptor_;
 
   /* Total sample count.  */
   gcov_type total_count_;
@@ -541,8 +596,9 @@ public:
   /* For a given DECL, returns the top-level function_instance.  */
   function_instance *get_function_instance_by_decl (tree decl) const;
 
-  /* For a given name index, returns the top-level function_instance.  */
-  function_instance *get_function_instance_by_name_index (int) const;
+  /* For a given DESCRIPTOR, return the matching instance if found.  */
+  function_instance *
+    get_function_instance_by_descriptor (function_instance::descriptor) const;
 
   void add_function_instance (function_instance *);
 
@@ -572,10 +628,12 @@ public:
   void offline_external_functions ();
 
   void offline_unrealized_inlines ();
+
 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 pair of function_instance filename and symbol name (in
+     string_table) to function_instance.  */
+  typedef std::map<function_instance::descriptor, function_instance *>
+    name_function_instance_map;
 
   autofdo_source_profile () {}
 
@@ -587,6 +645,21 @@ private:
   function_instance *
   get_function_instance_by_inline_stack (const inline_stack &stack) const;
 
+  /* Find the matching function instance which has DESCRIPTOR as its
+     descriptor.  If not found, also try checking if an instance exists with 
the
+     same name which has no associated filename.  */
+  name_function_instance_map::const_iterator find_iter_for_function_instance (
+    function_instance::descriptor descriptor) const;
+
+  /* Similar to the above, but return a pointer to the instance instead of an
+     iterator.  */
+  function_instance *
+  find_function_instance (function_instance::descriptor descriptor) const;
+
+  /* Remove a function instance from the map.  Returns true if the entry was
+     actually deleted.  */
+  bool remove_function_instance (function_instance *inst);
+
   name_function_instance_map map_;
 
   auto_vec <function_instance *> duplicate_functions_;
@@ -826,14 +899,29 @@ get_relative_location_for_stmt (tree fn, gimple *stmt)
           gimple_location (stmt));
 }
 
+/* Return either the basename or the realpath for a given path based on
+   PARAM_PROFILE_FUNC_INTERNAL_ID.  */
+
+static const char *
+get_normalized_path (const char *path, bool from_gcov = false)
+{
+  if (param_profile_func_internal_id == 1)
+    /* The GCOV will already contain the entire path.  It doesn't need to be
+       normalized with lrealpath ().  */
+    return from_gcov ? path : lrealpath (path);
+  return lbasename (path);
+}
+
 /* Member functions for string_table.  */
 
 /* Deconstructor.  */
 
 string_table::~string_table ()
 {
-  for (unsigned i = 0; i < vector_.length (); i++)
-    free (vector_[i]);
+  for (unsigned i = 0; i < symbol_names_.length (); i++)
+    free (const_cast<char *> (symbol_names_[i]));
+  for (unsigned i = 0; i < filenames_.length (); i++)
+    free (const_cast<char *> (filenames_[i]));
 }
 
 
@@ -845,8 +933,8 @@ string_table::get_index (const char *name) const
 {
   if (name == NULL)
     return -1;
-  string_index_map::const_iterator iter = map_.find (name);
-  if (iter == map_.end ())
+  string_index_map::const_iterator iter = symbol_name_map_.find (name);
+  if (iter == symbol_name_map_.end ())
     return -1;
 
   return iter->second;
@@ -871,20 +959,79 @@ string_table::get_index_by_decl (tree decl) const
 /* Return the function name of a given INDEX.  */
 
 const char *
-string_table::get_name (int index) const
+string_table::get_symbol_name (int index) const
+{
+  gcc_assert (index > 0 && index < (int) symbol_names_.length ());
+  return symbol_names_[index];
+}
+
+/* For a given index, returns the string.  */
+
+const char *
+string_table::get_filename (int index) const
+{
+  /* There may not be any file name for some functions, ignore them.  */
+  if (index == string_table::unknown_filename)
+    return "<unknown>";
+  gcc_assert (index >= 0 && index < (int) filenames_.length ());
+  return filenames_[index];
+}
+
+/* For a given symbol name index, returns the filename index.  */
+
+int
+string_table::get_filename_by_symbol (int index) const
 {
-  gcc_assert (index > 0 && index < (int)vector_.length ());
-  return vector_[index];
+  return get_filename_by_symbol (get_symbol_name (index));
 }
 
-/* Add new name SRRING and return its index.  */
+/* For a given function name, returns the filename index.  */
 
 int
-string_table::add_name (char *string)
+string_table::get_filename_by_symbol (const char *name) const
 {
-  vector_.safe_push (string);
-  map_[vector_.last ()] = vector_.length () - 1;
-  return vector_.length () - 1;
+  auto it = symbol_to_filename_map_.find (name);
+  if (it != symbol_to_filename_map_.end () && it->second < filenames_.length 
())
+    return it->second;
+  return string_table::unknown_filename;
+}
+
+/* For a given filename, returns the index.  */
+
+int
+string_table::get_filename_index (const char *name) const
+{
+  auto iter = filename_map_.find (name);
+  return iter == filename_map_.end () ? string_table::unknown_filename
+                                     : iter->second;
+}
+
+/* Add new symbol name STRING (with an associated file name FILENAME_IDX) and
+   return its index.  */
+
+int
+string_table::add_symbol_name (const char *string, int filename_idx)
+{
+  gcc_assert (
+    filename_idx == string_table::unknown_filename
+    || (filename_idx >= 0 && filename_idx < (int) filenames_.length ()));
+  symbol_names_.safe_push (string);
+  symbol_name_map_[symbol_names_.last ()] = symbol_names_.length () - 1;
+  symbol_to_filename_map_[symbol_names_.last ()] = filename_idx;
+  return symbol_names_.length () - 1;
+}
+
+/* Add new filename and return its index (returning the same if it already
+   exists).  */
+
+int
+string_table::add_filename (const char *name)
+{
+  auto it = filename_map_.find (name);
+  if (it != filename_map_.end ())
+    return it->second;
+  filenames_.safe_push (xstrdup (name));
+  return filenames_.length () - 1;
 }
 
 /* Read the string table. Return TRUE if reading is successful.  */
@@ -897,12 +1044,26 @@ string_table::read ()
   /* Skip the length of the section.  */
   gcov_read_unsigned ();
   /* Read in the file name table.  */
+  unsigned file_num = gcov_read_unsigned ();
+  filenames_.reserve (file_num);
+  for (unsigned i = 0; i < file_num; i++)
+    {
+      const char *filename = gcov_read_string ();
+      filenames_.quick_push (xstrdup (get_normalized_path (filename, true)));
+      filename_map_[filenames_.last ()] = i;
+      free (const_cast<char *> (filename));
+      if (gcov_is_error ())
+       return false;
+    }
+  /* Read in the function name -> file name table.  */
   unsigned string_num = gcov_read_unsigned ();
-  vector_.reserve (string_num);
+  symbol_names_.reserve (string_num);
   for (unsigned i = 0; i < string_num; i++)
     {
-      vector_.quick_push (xstrdup (gcov_read_string ()));
-      map_[vector_.last ()] = i;
+      symbol_names_.quick_push (const_cast<char *> (gcov_read_string ()));
+      symbol_name_map_[symbol_names_.last ()] = i;
+      unsigned filename_idx = gcov_read_unsigned ();
+      symbol_to_filename_map_[symbol_names_.last ()] = filename_idx;
       if (gcov_is_error ())
        return false;
     }
@@ -914,7 +1075,7 @@ string_table::read ()
 cgraph_node *
 string_table::get_cgraph_node (int name_index)
 {
-  const char *sname = get_name (name_index);
+  const char *sname = get_symbol_name (name_index);
 
   symtab_node *n = cgraph_node::get_for_asmname (get_identifier (sname));
   for (;n; n = n->next_sharing_asm_name)
@@ -929,7 +1090,7 @@ string_table::get_cgraph_node (int name_index)
 cgraph_node *
 function_instance::get_cgraph_node ()
 {
-  return afdo_string_table->get_cgraph_node (name ());
+  return afdo_string_table->get_cgraph_node (symbol_name ());
 }
 
 /* Member functions for function_instance.  */
@@ -974,9 +1135,9 @@ function_instance::get_function_instance_by_decl (unsigned 
lineno,
                           dump_user_location_t::from_location_t (location),
                           "auto-profile has mismatched function name %s"
                           " insteed of %s at loc %i:%i",
-                          afdo_string_table->get_name (iter.first.second),
-                          raw_symbol_name (decl),
-                          lineno >> 16,
+                          afdo_string_table->get_symbol_name (
+                            iter.first.second),
+                          raw_symbol_name (decl), lineno >> 16,
                           lineno & 65535);
     }
 
@@ -991,7 +1152,12 @@ function_instance::merge (function_instance *other,
                          vec <function_instance *> &new_functions)
 {
   /* Do not merge to itself and only merge functions of same name.  */
-  gcc_checking_assert (other != this && other->name () == name ());
+  gcc_checking_assert (other != this
+                      && other->symbol_name () == symbol_name ());
+
+  if (file_name () != other->file_name ())
+    return;
+
   total_count_ += other->total_count_;
   if (other->total_count () && total_count () && other->head_count () == -1)
     head_count_ = -1;
@@ -1111,7 +1277,8 @@ function_instance::offline (function_instance *fn,
       gcc_checking_assert (s->total_count_ >= 0);
     }
   function_instance *to
-    = afdo_source_profile->get_function_instance_by_name_index (fn->name ());
+    = afdo_source_profile->get_function_instance_by_descriptor (
+      fn->get_descriptor ());
   fn->set_inlined_to (NULL);
   /* If there is offline function of same name, we need to merge profile.
      Delay this by adding function to a worklist so we do not run into
@@ -1186,7 +1353,8 @@ match_with_target (cgraph_node *n,
 {
   cgraph_node *callee = orig_callee->ultimate_alias_target ();
   const char *symbol_name = raw_symbol_name (callee->decl);
-  const char *name = afdo_string_table->get_name (inlined_fn->name ());
+  const char *name
+    = afdo_string_table->get_symbol_name (inlined_fn->symbol_name ());
   if (strcmp (name, symbol_name))
     {
       int i;
@@ -1200,18 +1368,21 @@ match_with_target (cgraph_node *n,
        }
       /* Accept dwarf names and stripped suffixes.  */
       if (!strcmp (lang_hooks.dwarf_name (callee->decl, 0),
-                  afdo_string_table->get_name (inlined_fn->name ()))
-         || (!name[i] && symbol_name[i] == '.')
-         || in_suffix)
+                  afdo_string_table->get_symbol_name (
+                    inlined_fn->symbol_name ()))
+         || (!name[i] && symbol_name[i] == '.') || in_suffix)
        {
          int index = afdo_string_table->get_index (symbol_name);
          if (index == -1)
-           index = afdo_string_table->add_name (xstrdup (symbol_name));
+           index = afdo_string_table->add_symbol_name (
+             xstrdup (symbol_name),
+             afdo_string_table->add_filename (
+               get_normalized_path (DECL_SOURCE_FILE (callee->decl))));
          if (dump_file)
            fprintf (dump_file,
                     "  Renaming inlined call target %s to %s\n",
                     name, symbol_name);
-         inlined_fn->set_name (index);
+         inlined_fn->set_symbol_name (index);
          return 2;
        }
       /* Only warn about declarations.  It is possible that the function
@@ -1493,10 +1664,9 @@ function_instance::match (cgraph_node *node,
                                       "auto-profile of %q+F seem to contain"
                                       " lost discriminator %i for"
                                       " call of %s at relative location %i",
-                                      node->decl,
-                                      loc & 65535,
-                                      afdo_string_table->get_name
-                                        (inlined_fn_nodisc->name ()),
+                                      node->decl, loc & 65535,
+                                      afdo_string_table->get_symbol_name (
+                                        inlined_fn_nodisc->symbol_name ()),
                                       loc >> 16))
                            inform (gimple_location (stmt),
                                    "corresponding call");
@@ -1512,19 +1682,18 @@ function_instance::match (cgraph_node *node,
                    {
                      if (inlined_fn)
                        {
-                         int old_name = inlined_fn->name ();
+                         int old_name = inlined_fn->symbol_name ();
                          int r = match_with_target (node, stmt, inlined_fn,
                                                     callee_node);
                          if (r == 2)
                            {
                              auto iter = callsites.find ({loc, old_name});
-                             gcc_checking_assert (old_name
-                                                  != inlined_fn->name ()
-                                                  && iter != callsites.end ()
-                                                  && iter->second
-                                                     == inlined_fn);
+                             gcc_checking_assert (
+                               old_name != inlined_fn->symbol_name ()
+                               && iter != callsites.end ()
+                               && iter->second == inlined_fn);
                              callsite key2 = {stack[0].afdo_loc,
-                                               inlined_fn->name ()};
+                                              inlined_fn->symbol_name ()};
                              callsites.erase (iter);
                              callsites[key2] = inlined_fn;
                            }
@@ -1575,23 +1744,24 @@ function_instance::match (cgraph_node *node,
                            (gimple_location (stmt));
                          /* Do renaming if needed so we can look up
                             cgraph node and recurse into inlined function.  */
-                         int *newn = to_symbol_name.get (inlined_fn->name ());
-                         gcc_checking_assert
-                           (!newn || *newn != inlined_fn->name ());
+                         int *newn
+                           = to_symbol_name.get (inlined_fn->symbol_name ());
+                         gcc_checking_assert (
+                           !newn || *newn != inlined_fn->symbol_name ());
                          if (newn || lost_discriminator)
                            {
-                             auto iter = callsites.find
-                                           ({loc, inlined_fn->name ()});
+                             auto iter = callsites.find (
+                               {loc, inlined_fn->symbol_name ()});
                              gcc_checking_assert (iter != callsites.end ()
                                                   && iter->second
                                                      == inlined_fn);
-                             callsite key2 = {stack[0].afdo_loc,
-                                              newn ? *newn
-                                              : inlined_fn->name ()};
+                             callsite key2
+                               = {stack[0].afdo_loc,
+                                  newn ? *newn : inlined_fn->symbol_name ()};
                              callsites.erase (iter);
                              callsites[key2] = inlined_fn;
-                             inlined_fn->set_name (newn ? *newn
-                                                   : inlined_fn->name ());
+                             inlined_fn->set_symbol_name (
+                               newn ? *newn : inlined_fn->symbol_name ());
                            }
                          functions.add (inlined_fn);
                        }
@@ -1682,8 +1852,8 @@ function_instance::match (cgraph_node *node,
            fprintf (dump_file, ":%" PRIu64, iter->second.count);
            for (auto &titer : iter->second.targets)
              fprintf (dump_file, " %s:%" PRIu64,
-                      afdo_string_table->get_name (titer.first),
-                      (int64_t)titer.second);
+                      afdo_string_table->get_symbol_name (titer.first),
+                      (int64_t) titer.second);
            fprintf (dump_file, "\n");
          }
        iter = pos_counts.erase (iter);
@@ -1709,9 +1879,9 @@ function_instance::match (cgraph_node *node,
              inform (DECL_SOURCE_LOCATION (node->decl),
                      "call of %s with total count %" PRId64
                      ", relative location +%i, discriminator %i",
-                     afdo_string_table->get_name (iter->first.second),
-                     iter->second->total_count (),
-                     iter->first.first >> 16, iter->first.first & 65535);
+                     afdo_string_table->get_symbol_name (iter->first.second),
+                     iter->second->total_count (), iter->first.first >> 16,
+                     iter->first.first & 65535);
            if ((iter->first.first >> 16) > (end_location >> 16) && warned)
              inform (DECL_SOURCE_LOCATION (node->decl),
                      "location is after end of function");
@@ -1772,8 +1942,8 @@ function_instance::remove_external_functions
       }
     else
       {
-       gcc_checking_assert ((int)iter->first.second
-                            == iter->second->name ());
+       gcc_checking_assert ((int) iter->first.second
+                            == iter->second->symbol_name ());
        int *newn = iter->second->get_call_location () == UNKNOWN_LOCATION
                    ? to_symbol_name.get (iter->first.second)
                    : NULL;
@@ -1791,7 +1961,7 @@ function_instance::remove_external_functions
       auto iter = callsites.find (key);
       callsite key2 = key;
       key2.second = *to_symbol_name.get (key.second);
-      iter->second->set_name (key2.second);
+      iter->second->set_symbol_name (key2.second);
       callsites.erase (iter);
       callsites[key2] = iter->second;
     }
@@ -1852,9 +2022,9 @@ void
 function_instance::dump (FILE *f, int indent, bool nested) const
 {
   if (!nested)
-    fprintf (f, "%*s%s total:%" PRIu64 " head:%" PRId64 "\n",
-            indent, "", afdo_string_table->get_name (name ()),
-            (int64_t)total_count (), (int64_t)head_count ());
+    fprintf (f, "%*s%s total:%" PRIu64 " head:%" PRId64 "\n", indent, "",
+            afdo_string_table->get_symbol_name (symbol_name ()),
+            (int64_t) total_count (), (int64_t) head_count ());
   else
     fprintf (f, " total:%" PRIu64 "\n", (int64_t)total_count ());
   for (auto const &iter : pos_counts)
@@ -1865,17 +2035,19 @@ function_instance::dump (FILE *f, int indent, bool 
nested) const
 
       for (auto const &titer : iter.second.targets)
        fprintf (f, "  %s:%" PRIu64,
-                afdo_string_table->get_name (titer.first),
-                (int64_t)titer.second);
+                afdo_string_table->get_symbol_name (titer.first),
+                (int64_t) titer.second);
       fprintf (f,"\n");
     }
   for (auto const &iter : callsites)
     {
       fprintf (f, "%*s", indent + 2, "");
       dump_afdo_loc (f, iter.first.first);
-      fprintf (f, ": %s", afdo_string_table->get_name (iter.first.second));
+      fprintf (f, ": %s",
+              afdo_string_table->get_symbol_name (iter.first.second));
       iter.second->dump (f, indent + 2, true);
-      gcc_checking_assert ((int)iter.first.second == iter.second->name ());
+      gcc_checking_assert ((int) iter.first.second
+                          == iter.second->symbol_name ());
     }
 }
 
@@ -1893,9 +2065,9 @@ function_instance::dump_inline_stack (FILE *f) const
           iter != s->callsites.end (); ++iter)
        if (iter->second == p)
          {
-           gcc_checking_assert (!found
-                                && (int)iter->first.second == p->name ());
-           stack.safe_push ({iter->first.first, s->name ()});
+           gcc_checking_assert (
+             !found && (int) iter->first.second == p->symbol_name ());
+           stack.safe_push ({iter->first.first, s->symbol_name ()});
            found = true;
          }
       gcc_checking_assert (found);
@@ -1904,11 +2076,11 @@ function_instance::dump_inline_stack (FILE *f) const
     }
   for (callsite &s: stack)
     {
-      fprintf (f, "%s:", afdo_string_table->get_name (s.second));
+      fprintf (f, "%s:", afdo_string_table->get_symbol_name (s.second));
       dump_afdo_loc (f, s.first);
       fprintf (f, " ");
     }
-  fprintf (f, "%s", afdo_string_table->get_name (name ()));
+  fprintf (f, "%s", afdo_string_table->get_symbol_name (symbol_name ()));
 }
 
 /* Dump instance to stderr.  */
@@ -1944,13 +2116,13 @@ function_instance::find_icall_target_map (tree fn, 
gcall *stmt,
   for (callsite_map::const_iterator iter = callsites.begin ();
        iter != callsites.end (); ++iter)
     {
-      unsigned callee = iter->second->name ();
+      unsigned callee = iter->second->symbol_name ();
       /* Check if callsite location match the stmt.  */
       if (iter->first.first != stmt_offset
          || iter->second->removed_icall_target ())
        continue;
       struct cgraph_node *node = cgraph_node::get_for_asmname (
-          get_identifier (afdo_string_table->get_name (callee)));
+       get_identifier (afdo_string_table->get_symbol_name (callee)));
       if (node == NULL)
         continue;
       (*map)[callee] = iter->second->total_count () * afdo_count_scale;
@@ -1996,7 +2168,7 @@ autofdo_source_profile::offline_external_functions ()
      .isra, .ipcp.  */
   for (size_t i = 1; i < afdo_string_table->num_entries (); i++)
     {
-      const char *n1 = afdo_string_table->get_name (i);
+      const char *n1 = afdo_string_table->get_symbol_name (i);
       char *n2 = get_original_name (n1);
       if (!strcmp (n1, n2))
        {
@@ -2004,7 +2176,7 @@ autofdo_source_profile::offline_external_functions ()
          /* Watch for duplicate entries.
             This seems to happen in practice and may be useful to distingush
             multiple static symbols of the same name, but we do not realy
-            have a way to differentiate them in get_name lookup.  */
+            have a way to differentiate them in get_symbol_name lookup.  */
          int index = afdo_string_table->get_index (n1);
          if (index != (int)i)
            {
@@ -2020,10 +2192,9 @@ autofdo_source_profile::offline_external_functions ()
        fprintf (dump_file, "Adding rename removing clone suffxes %s -> %s\n",
                 n1, n2);
       int index = afdo_string_table->get_index (n2);
-      if (index != -1)
-       free (n2);
-      else
-       index = afdo_string_table->add_name (n2);
+      if (index == -1)
+       index = afdo_string_table->add_symbol_name (xstrdup (n2),
+                                                   
string_table::unknown_filename);
       to_symbol_name.put (i, index);
     }
   last_name = afdo_string_table->num_entries ();
@@ -2042,11 +2213,14 @@ autofdo_source_profile::offline_external_functions ()
          if (index2 != -1)
            {
              if (index == -1)
-               index = afdo_string_table->add_name (xstrdup (name));
+               index = afdo_string_table->add_symbol_name (
+                 xstrdup (name),
+                 afdo_string_table->add_filename (
+                   get_normalized_path (DECL_SOURCE_FILE (node->decl))));
              if (dump_file)
                {
                  fprintf (dump_file, "Adding dwarf->symbol rename %s -> %s\n",
-                          afdo_string_table->get_name (index2), name);
+                          afdo_string_table->get_symbol_name (index2), name);
                  if (to_symbol_name.get (index2))
                    fprintf (dump_file, "Dwarf name is not unique");
                }
@@ -2058,7 +2232,7 @@ autofdo_source_profile::offline_external_functions ()
        {
          if (dump_file)
            fprintf (dump_file, "%s is defined in node %s\n",
-                    afdo_string_table->get_name (index),
+                    afdo_string_table->get_symbol_name (index),
                     node->dump_name ());
          seen.add (index);
        }
@@ -2109,10 +2283,10 @@ autofdo_source_profile::offline_external_functions ()
   auto_vec <function_instance *, 20>fns2;
   /* Poppulate worklist with all functions to process.  Processing
      may introduce new functions by offlining.  */
-  for (auto const &iter : map_)
+  for (auto &function : map_)
     {
-      iter.second->set_in_worklist ();
-      fns.safe_push (iter.second);
+      function.second->set_in_worklist ();
+      fns.safe_push (function.second);
     }
 
   /* There are two worklists.  First all functions needs to be matched
@@ -2124,7 +2298,7 @@ autofdo_source_profile::offline_external_functions ()
       /* In case renaming introduced new name, keep seen up to date.  */
       for (; last_name < afdo_string_table->num_entries (); last_name++)
        {
-         const char *name = afdo_string_table->get_name (last_name);
+         const char *name = afdo_string_table->get_symbol_name (last_name);
          symtab_node *n
            = afdo_string_table->get_cgraph_node (last_name);
          if (dump_file)
@@ -2139,20 +2313,19 @@ autofdo_source_profile::offline_external_functions ()
          function_instance *f = fns.pop ();
          if (f->get_location () == UNKNOWN_LOCATION)
            {
-             int index = f->name ();
+             int index = f->symbol_name ();
              int *newn = to_symbol_name.get (index);
              if (newn)
                {
-                 f->set_name (*newn);
-                 if (map_.count (index)
-                     && map_[index] == f)
-                   map_.erase (index);
-                 if (!map_.count (*newn))
-                   map_[*newn] = f;
+                 if (find_function_instance (f->get_descriptor ()) == f)
+                   remove_function_instance (f);
+                 f->set_symbol_name (*newn);
+                 if (!find_function_instance (f->get_descriptor ()))
+                   add_function_instance (f);
                }
              if (cgraph_node *n = f->get_cgraph_node ())
                {
-                 gcc_checking_assert (seen.contains (f->name ()));
+                 gcc_checking_assert (seen.contains (f->symbol_name ()));
                  f->match (n, fns, to_symbol_name);
                }
            }
@@ -2161,12 +2334,14 @@ autofdo_source_profile::offline_external_functions ()
       else
        {
          function_instance *f = fns2.pop ();
-         int index = f->name ();
+         int index = f->symbol_name ();
          gcc_checking_assert (f->in_worklist_p ());
 
          /* If map has different function_instance of same name, then
             this is a duplicated entry which needs to be merged.  */
-         if (map_.count (index) && map_[index] != f)
+         function_instance *index_inst
+           = find_function_instance (f->get_descriptor ());
+         if (index_inst && index_inst != f)
            {
              if (dump_file)
                {
@@ -2174,7 +2349,7 @@ autofdo_source_profile::offline_external_functions ()
                  f->dump_inline_stack (dump_file);
                  fprintf (dump_file, "\n");
                }
-             map_[index]->merge (f, fns);
+             index_inst->merge (f, fns);
              gcc_checking_assert (!f->inlined_to ());
              f->clear_in_worklist ();
              delete f;
@@ -2186,9 +2361,10 @@ autofdo_source_profile::offline_external_functions ()
              f->clear_in_worklist ();
              if (dump_file)
                fprintf (dump_file, "Removing external %s\n",
-                        afdo_string_table->get_name (f->name ()));
-             if (map_.count (index) && map_[index] == f)
-               map_.erase (f->name ());
+                        afdo_string_table->get_symbol_name (
+                          f->symbol_name ()));
+             if (index_inst == f)
+               remove_function_instance (f);
              delete f;
            }
          /* If this is offline function instance seen in this
@@ -2202,10 +2378,10 @@ autofdo_source_profile::offline_external_functions ()
        }
     }
   if (dump_file)
-    for (auto const &iter : map_)
+    for (auto const &function : map_)
       {
-       seen.contains (iter.second->name ());
-       iter.second->dump (dump_file);
+       seen.contains (function.second->symbol_name ());
+       function.second->dump (dump_file);
       }
 }
 
@@ -2259,22 +2435,24 @@ autofdo_source_profile::offline_unrealized_inlines ()
   auto_vec <function_instance *>fns;
   /* Poppulate worklist with all functions to process.  Processing
      may introduce new functions by offlining.  */
-  for (auto const &iter : map_)
+  for (auto const &function : map_)
     {
-      fns.safe_push (iter.second);
-      iter.second->set_in_worklist ();
+      fns.safe_push (function.second);
+      function.second->set_in_worklist ();
     }
   while (fns.length ())
     {
       function_instance *f = fns.pop ();
-      int index = f->name ();
-      bool in_map = map_.count (index);
+      int index = f->symbol_name ();
+      function_instance *index_inst
+       = find_function_instance (f->get_descriptor ());
+      bool in_map = index_inst != nullptr;
       if (in_map)
        if (cgraph_node *n = f->get_cgraph_node ())
          {
            if (dump_file)
              fprintf (dump_file, "Marking realized %s\n",
-                      afdo_string_table->get_name (index));
+                      afdo_string_table->get_symbol_name (index));
            f->set_realized ();
            if (DECL_INITIAL (n->decl)
                && DECL_INITIAL (n->decl) != error_mark_node)
@@ -2285,7 +2463,7 @@ autofdo_source_profile::offline_unrealized_inlines ()
                           && f->in_worklist_p ());
 
       /* If this is duplicated instance, merge it into one in map.  */
-      if (in_map && map_[index] != f)
+      if (in_map && index_inst != f)
        {
          if (dump_file)
            {
@@ -2293,7 +2471,7 @@ autofdo_source_profile::offline_unrealized_inlines ()
              f->dump_inline_stack (dump_file);
              fprintf (dump_file, "\n");
            }
-         map_[index]->merge (f, fns);
+         index_inst->merge (f, fns);
          f->clear_in_worklist ();
          gcc_checking_assert (!f->inlined_to ());
          delete f;
@@ -2303,8 +2481,8 @@ autofdo_source_profile::offline_unrealized_inlines ()
        {
          if (dump_file)
            fprintf (dump_file, "Removing optimized out function %s\n",
-                    afdo_string_table->get_name (f->name ()));
-         map_.erase (index);
+                    afdo_string_table->get_symbol_name (f->symbol_name ()));
+         remove_function_instance (index_inst);
          f->clear_in_worklist ();
          delete f;
        }
@@ -2312,8 +2490,8 @@ autofdo_source_profile::offline_unrealized_inlines ()
        f->clear_in_worklist ();
     }
   if (dump_file)
-    for (auto const &iter : map_)
-      iter.second->dump (dump_file);
+    for (auto const &function : map_)
+      function.second->dump (dump_file);
 }
 
 /* Read the profile and create a function_instance with head count as
@@ -2354,7 +2532,10 @@ function_instance::read_function_instance 
(function_instance_stack *stack,
   unsigned name = gcov_read_unsigned ();
   unsigned num_pos_counts = gcov_read_unsigned ();
   unsigned num_callsites = gcov_read_unsigned ();
-  function_instance *s = new function_instance (name, head_count);
+  function_instance *s
+    = new function_instance (name,
+                            afdo_string_table->get_filename_by_symbol (name),
+                            head_count);
   if (!stack->is_empty ())
     s->set_inlined_to (stack->last ());
   stack->safe_push (s);
@@ -2383,8 +2564,9 @@ function_instance::read_function_instance 
(function_instance_stack *stack,
       unsigned offset = gcov_read_unsigned ();
       function_instance *callee_function_instance
           = read_function_instance (stack, -1);
-      s->callsites[std::make_pair (offset, callee_function_instance->name ())]
-          = callee_function_instance;
+      s->callsites[std::make_pair (offset,
+                                  callee_function_instance->symbol_name ())]
+       = callee_function_instance;
     }
   stack->pop ();
   return s;
@@ -2404,21 +2586,23 @@ autofdo_source_profile::~autofdo_source_profile ()
 function_instance *
 autofdo_source_profile::get_function_instance_by_decl (tree decl) const
 {
+  const char *filename = get_normalized_path (DECL_SOURCE_FILE (decl));
   int index = afdo_string_table->get_index_by_decl (decl);
   if (index == -1)
     return NULL;
-  name_function_instance_map::const_iterator ret = map_.find (index);
-  return ret == map_.end () ? NULL : ret->second;
+
+  function_instance::descriptor descriptor (
+    afdo_string_table->get_filename_index (filename), index);
+  return find_function_instance (descriptor);
 }
 
-/* For a given NAME_INDEX, returns the top-level function_instance.  */
+/* For a given DESCRIPTOR, return the matching instance if found.  */
 
 function_instance *
-autofdo_source_profile::get_function_instance_by_name_index (int name_index)
-               const
+autofdo_source_profile::get_function_instance_by_descriptor (
+  function_instance::descriptor descriptor) const
 {
-  name_function_instance_map::const_iterator ret = map_.find (name_index);
-  return ret == map_.end () ? NULL : ret->second;
+  return find_function_instance (descriptor);
 }
 
 /* Add function instance FN.  */
@@ -2426,9 +2610,8 @@ 
autofdo_source_profile::get_function_instance_by_name_index (int name_index)
 void
 autofdo_source_profile::add_function_instance (function_instance *fn)
 {
-  int index = fn->name ();
-  gcc_checking_assert (map_.count (index) == 0);
-  map_[index] = fn;
+  gcc_checking_assert (map_.find (fn->get_descriptor ()) == map_.end ());
+  map_[fn->get_descriptor ()] = fn;
 }
 
 /* Find count_info for a given gimple STMT. If found, store the count_info
@@ -2587,12 +2770,13 @@ autofdo_source_profile::get_callsite_total_count (
        fprintf (dump_file, "No function instance found\n");
       return 0;
     }
-  if (afdo_string_table->get_index_by_decl (edge->callee->decl) != s->name ())
+  if (afdo_string_table->get_index_by_decl (edge->callee->decl)
+      != s->symbol_name ())
     {
       if (dump_file)
        fprintf (dump_file, "Mismatched name of callee %s and profile %s\n",
                 raw_symbol_name (edge->callee->decl),
-                afdo_string_table->get_name (s->name ()));
+                afdo_string_table->get_symbol_name (s->symbol_name ()));
       return 0;
     }
 
@@ -2632,17 +2816,16 @@ autofdo_source_profile::read ()
   for (unsigned i = 0; i < function_num; i++)
     {
       function_instance::function_instance_stack stack;
-      function_instance *s = function_instance::read_function_instance (
-          &stack, gcov_read_counter ());
-      int fun_id = s->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;
+      function_instance *s
+       = function_instance::read_function_instance (&stack,
+                                                    gcov_read_counter ());
+
+      if (find_function_instance (s->get_descriptor ()) == nullptr)
+       add_function_instance (s);
       else
        fatal_error (UNKNOWN_LOCATION,
                     "auto-profile contains duplicated function instance %s",
-                    afdo_string_table->get_name (s->name ()));
+                    afdo_string_table->get_symbol_name (s->symbol_name ()));
     }
   int hot_frac = param_hot_bb_count_fraction;
   /* Scale up the profile, but leave some bits in case some counts gets
@@ -2679,16 +2862,20 @@ function_instance *
 autofdo_source_profile::get_function_instance_by_inline_stack (
     const inline_stack &stack) const
 {
-  name_function_instance_map::const_iterator iter = map_.find (
-      afdo_string_table->get_index_by_decl (stack[stack.length () - 1].decl));
-  if (iter == map_.end ())
+  function_instance::descriptor descriptor (
+    afdo_string_table->get_filename_index (
+      get_normalized_path (DECL_SOURCE_FILE (stack[stack.length () - 
1].decl))),
+    afdo_string_table->get_index_by_decl (stack[stack.length () - 1].decl));
+  function_instance *s = find_function_instance (descriptor);
+
+  if (s == NULL)
     {
       if (dump_file)
        fprintf (dump_file, "No offline instance for %s\n",
                 raw_symbol_name (stack[stack.length () - 1].decl));
       return NULL;
     }
-  function_instance *s = iter->second;
+
   for (unsigned i = stack.length () - 1; i > 0; i--)
     {
       s = s->get_function_instance_by_decl (stack[i].afdo_loc,
@@ -2716,6 +2903,50 @@ 
autofdo_source_profile::get_function_instance_by_inline_stack (
   return s;
 }
 
+/* Find the matching function instance which has DESCRIPTOR as its
+   descriptor.  If not found, also try checking if an instance exists with the
+   same name which has no associated filename.  */
+
+autofdo_source_profile::name_function_instance_map::const_iterator
+autofdo_source_profile::find_iter_for_function_instance (
+  function_instance::descriptor descriptor) const
+{
+  auto it = map_.find (descriptor);
+
+  /* Try searching for the symbol not having a filename if it isn't found.  */
+  if (it == map_.end ())
+    it = map_.find (
+      function_instance::descriptor (string_table::unknown_filename,
+                                    (int) descriptor.symbol_name ()));
+  return it;
+}
+
+/* Similar to the above, but return a pointer to the instance instead of an
+   iterator.  */
+
+function_instance *
+autofdo_source_profile::find_function_instance (
+  function_instance::descriptor descriptor) const
+{
+  auto it = find_iter_for_function_instance (descriptor);
+  return it == map_.end () ? NULL : it->second;
+}
+
+/* Remove a function instance from the map.  Returns true if the entry was
+   actually deleted.  */
+
+bool
+autofdo_source_profile::remove_function_instance (function_instance *inst)
+{
+  auto iter = find_iter_for_function_instance (inst->get_descriptor ());
+  if (iter != map_.end ())
+    {
+      map_.erase (iter);
+      return true;
+    }
+  return false;
+}
+
 /* Module profile is only used by LIPO. Here we simply ignore it.  */
 
 static void
@@ -2840,12 +3071,12 @@ afdo_indirect_call (gcall *stmt, const icall_target_map 
&map,
     }
   total *= afdo_count_scale;
   struct cgraph_node *direct_call = cgraph_node::get_for_asmname (
-      get_identifier (afdo_string_table->get_name (max_iter->first)));
+    get_identifier (afdo_string_table->get_symbol_name (max_iter->first)));
   if (direct_call == NULL)
     {
       if (dump_file)
        fprintf (dump_file, "Failed to find cgraph node for %s\n",
-                afdo_string_table->get_name (max_iter->first));
+                afdo_string_table->get_symbol_name (max_iter->first));
       return false;
     }
 
-- 
2.44.0

Reply via email to