From bf4988a9159c255f6bae2a8da1e7f26ea8364e57 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 9 May 2019 13:58:41 -0400
Subject: [PATCH 25/46] FIXME: add per-function stats

---
 gcc/analyzer/impl-4.cc | 93 ++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 78 insertions(+), 15 deletions(-)

diff --git a/gcc/analyzer/impl-4.cc b/gcc/analyzer/impl-4.cc
index 26762ad..f78b0bf 100644
--- a/gcc/analyzer/impl-4.cc
+++ b/gcc/analyzer/impl-4.cc
@@ -845,6 +845,17 @@ class exploded_edge : public dedge
   const superedge *const m_sedge;
 };
 
+/* Statistics about aspects of an exploded_graph.  */
+
+struct stats
+{
+  stats ();
+  void log (logger *logger) const;
+
+  int m_num_nodes[NUM_POINT_KINDS];
+  int m_node_reuse_count;
+};
+
 /* An exploded_graph is a directed graph of unique <point, state> pairs.
    It also has a worklist of nodes that are waiting for their successors
    to be added to the graph.  */
@@ -883,6 +894,7 @@ public:
 		   const state_machine &sm,
 		   tree var, state_machine::state_t state) const;
 
+  stats *get_or_create_function_stats (function *fn);
   void log_stats () const;
 
 private:
@@ -903,8 +915,9 @@ private:
   const int m_verbosity;
 
   /* Stats.  */
-  int m_num_nodes[NUM_POINT_KINDS];
-  int m_node_reuse_count;
+  stats m_global_stats;
+  typedef hash_map<function *, stats *> function_stat_map_t;
+  function_stat_map_t m_per_function_stats;
 };
 
 /* A path within an exploded_graph: a sequence of edges.  */
@@ -3022,6 +3035,30 @@ exploded_edge::dump_dot (graphviz_out *gv) const
   pp_printf (pp, "\"];\n");
 }
 
+////////////////////////////////////////////////////////////////////////////
+
+/* struct stats.  */
+
+/* FIXME.  */
+
+stats::stats () : m_node_reuse_count (0)
+{
+  for (int i = 0; i < NUM_POINT_KINDS; i++)
+    m_num_nodes[i] = 0;
+}
+
+/* FIXME.  */
+
+void
+stats::log (logger *logger) const
+{
+  gcc_assert (logger);
+  for (int i = 0; i < NUM_POINT_KINDS; i++)
+    logger->log ("m_num_nodes[%s]: %i",
+		 point_kind_to_string (static_cast <enum point_kind> (i)),
+		 m_num_nodes[i]);
+  logger->log ("m_node_reuse_count: %i", m_node_reuse_count);
+}
 
 ////////////////////////////////////////////////////////////////////////////
 
@@ -3033,12 +3070,8 @@ exploded_graph::exploded_graph (const supergraph &sg, logger *logger,
 				int verbosity)
 : log_user (logger), m_sg (sg), m_ext_state (ext_state),
   m_purge_map (purge_map),
-  m_verbosity (verbosity),
-  m_node_reuse_count (0)
+  m_verbosity (verbosity)
 {
-  for (int i = 0; i < NUM_POINT_KINDS; i++)
-    m_num_nodes[i] = 0;
-
   m_origin = get_or_create_node (program_point (NULL, NULL, 0, PK_ORIGIN,
 						call_string ()),
 				 program_state (ext_state));
@@ -3083,12 +3116,15 @@ exploded_graph::get_or_create_node (const program_point &point,
   if (get_logger ())
     log ("pruned_state: %s", pruned_state.to_str (m_ext_state).c_str ());
 
+  stats *per_fn_stats = get_or_create_function_stats (point.get_function ());
+
   point_and_state ps (point, pruned_state);
   if (exploded_node **slot = m_point_and_state_to_node.get (ps))
     {
       /* An exploded_node for PS already exists.  */
       log ("reused EN: %i", (*slot)->m_index);
-      m_node_reuse_count++;
+      m_global_stats.m_node_reuse_count++;
+      per_fn_stats->m_node_reuse_count++;
       return *slot;
     }
 
@@ -3096,7 +3132,8 @@ exploded_graph::get_or_create_node (const program_point &point,
   exploded_node *node = new exploded_node (ps, m_ext_state, m_nodes.length ());
   add_node (node);
   m_point_and_state_to_node.put (ps, node);
-  ++m_num_nodes[node->get_point ().m_kind];
+  m_global_stats.m_num_nodes[node->get_point ().m_kind]++;
+  per_fn_stats->m_num_nodes[node->get_point ().m_kind]++;
 
   if (get_logger ())
     {
@@ -3142,7 +3179,8 @@ exploded_graph::process_worklist ()
 	 entry ENs, one per phi; the number of PK_AFTER_SUPERNODE ought
 	 to be equivalent to the number of supernodes multiplied by the
 	 number of states.  */
-      if (m_num_nodes[PK_AFTER_SUPERNODE]> m_sg.num_nodes () * 5)
+      // FIXME: do per function
+      if (m_global_stats.m_num_nodes[PK_AFTER_SUPERNODE]> m_sg.num_nodes () * 5)
 	{
 	  log ("bailing out; too many nodes");
 	  warning (0, "analysis bailed out early");
@@ -3690,19 +3728,44 @@ exploded_graph::prune_path (checker4_path *path,
 
 /* FIXME.  */
 
+stats *
+exploded_graph::get_or_create_function_stats (function *fn)
+{
+  if (stats **slot = m_per_function_stats.get (fn))
+    return *slot;
+  else
+    {
+      stats *new_stats = new stats ();
+      m_per_function_stats.put (fn, new_stats);
+      return new_stats;
+    }
+}
+
+/* FIXME.  */
+
 void
 exploded_graph::log_stats () const
 {
   if (!get_logger ())
     return;
 
+  JIT_LOG_SCOPE (get_logger ());
+
   log ("m_sg.num_nodes (): %i", m_sg.num_nodes ());
   log ("m_nodes.length (): %i", m_nodes.length ());
-  for (int i = 0; i < NUM_POINT_KINDS; i++)
-    log ("m_num_nodes[%s]: %i",
-	 point_kind_to_string (static_cast <enum point_kind> (i)),
-	 m_num_nodes[i]);
-  log ("m_node_reuse_count: %i", m_node_reuse_count);
+  log ("m_edges.length (): %i", m_edges.length ());
+
+  log ("global stats:");
+  m_global_stats.log (get_logger ());
+
+  for (function_stat_map_t::iterator iter = m_per_function_stats.begin ();
+       iter != m_per_function_stats.end ();
+       ++iter)
+    {
+      function *fn = (*iter).first;
+      log_scope s (get_logger (), function_name (fn));
+      (*iter).second->log (get_logger ());
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////
-- 
1.8.5.3

