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

Reply via email to