From: Dhruv Chawla <[email protected]>
Signed-off-by: Dhruv Chawla <[email protected]>
gcc/ChangeLog:
* auto-profile.cc (string_table::~string_table): Update to free
original_names_map_.
(string_table::original_names_map_): New member.
(string_table::clashing_names_map_): Likewise.
(string_table::get_original_name): New function.
(string_table::read): Figure out clashes while reading.
(autofdo_source_profile::offline_external_functions): Call
get_original_name.
---
gcc/auto-profile.cc | 82 ++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 78 insertions(+), 4 deletions(-)
diff --git a/gcc/auto-profile.cc b/gcc/auto-profile.cc
index 5e62c7f6b59..a24061e02fe 100644
--- a/gcc/auto-profile.cc
+++ b/gcc/auto-profile.cc
@@ -260,6 +260,11 @@ public:
/* For a given filename, returns the index. */
int get_filename_index (const char *name) const;
+ /* Get the original name and file name index for a node. This will return
the
+ name from the current TU if there are multiple symbols that map to
+ NAME. */
+ std::pair<const char *, int> get_original_name (const char *name) const;
+
/* Read profile, return TRUE on success. */
bool read ();
@@ -288,6 +293,9 @@ private:
string_index_map symbol_name_map_;
string_index_map filename_map_;
string_index_map symbol_to_filename_map_;
+
+ string_string_map original_names_map_;
+ clashing_name_map clashing_names_map_;
};
/* Profile of a function instance:
@@ -683,7 +691,6 @@ static gcov_type afdo_count_scale = 1;
/* Helper functions. */
-
/* Return the original name of NAME: strip the suffix that starts
with '.' for names that are generetad after auto-profile pass.
This is to match profiled names with the names in the IR at this stage.
@@ -922,6 +929,9 @@ string_table::~string_table ()
free (const_cast<char *> (symbol_names_[i]));
for (unsigned i = 0; i < filenames_.length (); i++)
free (const_cast<char *> (filenames_[i]));
+ for (auto it = original_names_map_.begin (); it != original_names_map_.end
();
+ it++)
+ free (it->second);
}
@@ -1006,6 +1016,50 @@ string_table::get_filename_index (const char *name) const
: iter->second;
}
+/* Get the original name and file name index for a node. This will return the
+ name from the current TU if there are multiple symbols that map to
+ NAME. */
+
+std::pair<const char *, int>
+string_table::get_original_name (const char *name) const
+{
+ /* Check if the un-prefixed name differs from the actual name. */
+ auto stripped = original_names_map_.find (name);
+
+ /* The original name for the symbol is its name, i.e. there are no
+ suffixes. */
+ if (stripped == original_names_map_.end ())
+ return {name, get_filename_by_symbol (name)};
+
+ /* Figure out if a clash exists. */
+ auto clash = clashing_names_map_.find (stripped->second);
+ gcc_assert (clash != clashing_names_map_.end ());
+
+ /* Try to find a function from the current TU. */
+ gcc_assert (clash->second.length () >= 1);
+ if (symtab_node *n
+ = cgraph_node::get_for_asmname (get_identifier (stripped->second));
+ n && is_a<cgraph_node *> (n))
+ for (cgraph_node *cn = dyn_cast<cgraph_node *> (n); cn;)
+ {
+ /* Check if there is a symbol in the current TU that has the same name
+ as in the GCOV. */
+ for (auto name : clash->second)
+ {
+ int filename_idx = get_filename_by_symbol (name);
+ if (cn->definition && cn->has_gimple_body_p ()
+ && !strcmp (get_normalized_path (DECL_SOURCE_FILE (cn->decl)),
+ get_filename (filename_idx)))
+ return {stripped->second, filename_idx};
+ }
+ cn = dyn_cast<cgraph_node *> (cn->next_sharing_asm_name);
+ }
+
+ /* No match found. Just stick to the current symbol and return the stripped
+ name. */
+ return {stripped->second, get_filename_by_symbol (name)};
+}
+
/* Add new symbol name STRING (with an associated file name FILENAME_IDX) and
return its index. */
@@ -1064,6 +1118,25 @@ string_table::read ()
symbol_name_map_[symbol_names_.last ()] = i;
unsigned filename_idx = gcov_read_unsigned ();
symbol_to_filename_map_[symbol_names_.last ()] = filename_idx;
+ char *original = const_cast<char *> (
+ autofdo::get_original_name (symbol_names_.last ()));
+ if (strcmp (original, symbol_names_.last ()))
+ {
+ /* Take ownership of ORIGINAL. */
+ original_names_map_[symbol_names_.last ()] = original;
+ clashing_names_map_[original].safe_push (i);
+ /* It is possible that a public symbol with the stripped name exists.
+ If it does exist, add it as well. */
+ auto publik = symbol_name_map_.find (original);
+ if (publik != symbol_name_map_.end ()
+ && clashing_names_map_.find (publik->first)
+ == clashing_names_map_.end ())
+ clashing_names_map_[publik->first].safe_push (publik->second);
+ }
+ else
+ /* There are no suffixes to remove. */
+ free (original);
+
if (gcov_is_error ())
return false;
}
@@ -2169,10 +2242,11 @@ autofdo_source_profile::offline_external_functions ()
for (size_t i = 1; i < afdo_string_table->num_entries (); i++)
{
const char *n1 = afdo_string_table->get_symbol_name (i);
- char *n2 = get_original_name (n1);
+ std::pair<const char *, int> name_filename
+ = afdo_string_table->get_original_name (n1);
+ const char *n2 = name_filename.first;
if (!strcmp (n1, n2))
{
- free (n2);
/* 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
@@ -2194,7 +2268,7 @@ autofdo_source_profile::offline_external_functions ()
int index = afdo_string_table->get_index (n2);
if (index == -1)
index = afdo_string_table->add_symbol_name (xstrdup (n2),
-
string_table::unknown_filename);
+ name_filename.second);
to_symbol_name.put (i, index);
}
last_name = afdo_string_table->num_entries ();
--
2.44.0