diff gcc/symbol-summary.h @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
line wrap: on
line diff
--- a/gcc/symbol-summary.h	Fri Oct 27 22:46:09 2017 +0900
+++ b/gcc/symbol-summary.h	Thu Oct 25 07:37:49 2018 +0900
@@ -1,5 +1,5 @@
 /* Callgraph summary data structure.
-   Copyright (C) 2014-2017 Free Software Foundation, Inc.
+   Copyright (C) 2014-2018 Free Software Foundation, Inc.
    Contributed by Martin Liska
 
 This file is part of GCC.
@@ -31,26 +31,23 @@
   function_summary();
 };
 
+/* Function summary is a helper class that is used to associate a data structure
+   related to a callgraph node.  Typical usage can be seen in IPA passes which
+   create a temporary pass-related structures.  The summary class registers
+   hooks that are triggered when a new node is inserted, duplicated and deleted.
+   A user of a summary class can ovewrite virtual methods than are triggered by
+   the summary if such hook is triggered.  Apart from a callgraph node, the user
+   is given a data structure tied to the node.
+
+   The function summary class can work both with a heap-allocated memory and
+   a memory gained by garbage collected memory.  */
+
 template <class T>
 class GTY((user)) function_summary <T *>
 {
 public:
   /* Default construction takes SYMTAB as an argument.  */
-  function_summary (symbol_table *symtab, bool ggc = false): m_ggc (ggc),
-    m_insertion_enabled (true), m_released (false), m_map (13, ggc),
-    m_symtab (symtab)
-  {
-    m_symtab_insertion_hook =
-      symtab->add_cgraph_insertion_hook
-      (function_summary::symtab_insertion, this);
-
-    m_symtab_removal_hook =
-      symtab->add_cgraph_removal_hook
-      (function_summary::symtab_removal, this);
-    m_symtab_duplication_hook =
-      symtab->add_cgraph_duplication_hook
-      (function_summary::symtab_duplication, this);
-  }
+  function_summary (symbol_table *symtab, bool ggc = false);
 
   /* Destructor.  */
   virtual ~function_summary ()
@@ -59,22 +56,7 @@
   }
 
   /* Destruction method that can be called for GGT purpose.  */
-  void release ()
-  {
-    if (m_released)
-      return;
-
-    m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook);
-    m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook);
-    m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook);
-
-    /* Release all summaries.  */
-    typedef typename hash_map <map_hash, T *>::iterator map_iterator;
-    for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
-      release ((*it).second);
-
-    m_released = true;
-  }
+  void release ();
 
   /* Traverses all summarys with a function F called with
      ARG as argument.  */
@@ -102,22 +84,37 @@
   }
 
   /* Release an item that is stored within map.  */
-  void release (T *item)
+  void release (T *item);
+
+  /* Getter for summary callgraph node pointer.  If a summary for a node
+     does not exist it will be created.  */
+  T* get_create (cgraph_node *node)
   {
-    if (m_ggc)
-      {
-	item->~T ();
-	ggc_free (item);
-      }
-    else
-      delete item;
+    bool existed;
+    T **v = &m_map.get_or_insert (node->get_uid (), &existed);
+    if (!existed)
+      *v = allocate_new ();
+
+    return *v;
   }
 
   /* Getter for summary callgraph node pointer.  */
-  T* get (cgraph_node *node)
+  T* get (cgraph_node *node) ATTRIBUTE_PURE
   {
-    gcc_checking_assert (node->summary_uid);
-    return get (node->summary_uid);
+    T **v = m_map.get (node->get_uid ());
+    return v == NULL ? NULL : *v;
+  }
+
+  /* Remove node from summary.  */
+  void remove (cgraph_node *node)
+  {
+    int uid = node->get_uid ();
+    T **v = m_map.get (uid);
+    if (v)
+      {
+	m_map.remove (uid);
+	release (*v);
+      }
   }
 
   /* Return number of elements handled by data structure.  */
@@ -129,7 +126,7 @@
   /* Return true if a summary for the given NODE already exists.  */
   bool exists (cgraph_node *node)
   {
-    return m_map.get (node->summary_uid) != NULL;
+    return m_map.get (node->get_uid ()) != NULL;
   }
 
   /* Enable insertion hook invocation.  */
@@ -145,50 +142,14 @@
   }
 
   /* Symbol insertion hook that is registered to symbol table.  */
-  static void symtab_insertion (cgraph_node *node, void *data)
-  {
-    gcc_checking_assert (node->summary_uid);
-    function_summary *summary = (function_summary <T *> *) (data);
-
-    if (summary->m_insertion_enabled)
-      summary->insert (node, summary->get (node));
-  }
+  static void symtab_insertion (cgraph_node *node, void *data);
 
   /* Symbol removal hook that is registered to symbol table.  */
-  static void symtab_removal (cgraph_node *node, void *data)
-  {
-    gcc_checking_assert (node->summary_uid);
-    function_summary *summary = (function_summary <T *> *) (data);
-
-    int summary_uid = node->summary_uid;
-    T **v = summary->m_map.get (summary_uid);
-
-    if (v)
-      {
-	summary->remove (node, *v);
-	summary->release (*v);
-	summary->m_map.remove (summary_uid);
-      }
-  }
+  static void symtab_removal (cgraph_node *node, void *data);
 
   /* Symbol duplication hook that is registered to symbol table.  */
   static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
-				  void *data)
-  {
-    function_summary *summary = (function_summary <T *> *) (data);
-    T **v = summary->m_map.get (node->summary_uid);
-
-    gcc_checking_assert (node2->summary_uid > 0);
-
-    if (v)
-      {
-	/* This load is necessary, because we insert a new value!  */
-	T *data = *v;
-	T *duplicate = summary->allocate_new ();
-	summary->m_map.put (node2->summary_uid, duplicate);
-	summary->duplicate (node, node2, data, duplicate);
-      }
-  }
+				  void *data);
 
 protected:
   /* Indication if we use ggc summary.  */
@@ -197,17 +158,6 @@
 private:
   typedef int_hash <int, 0, -1> map_hash;
 
-  /* Getter for summary callgraph ID.  */
-  T* get (int uid)
-  {
-    bool existed;
-    T **v = &m_map.get_or_insert (uid, &existed);
-    if (!existed)
-      *v = allocate_new ();
-
-    return *v;
-  }
-
   /* Indicates if insertion hook is enabled.  */
   bool m_insertion_enabled;
   /* Indicates if the summary is released.  */
@@ -230,6 +180,103 @@
 };
 
 template <typename T>
+function_summary<T *>::function_summary (symbol_table *symtab, bool ggc):
+  m_ggc (ggc), m_insertion_enabled (true), m_released (false), m_map (13, ggc),
+  m_symtab (symtab)
+{
+  m_symtab_insertion_hook
+    = symtab->add_cgraph_insertion_hook (function_summary::symtab_insertion,
+					 this);
+
+  m_symtab_removal_hook
+    = symtab->add_cgraph_removal_hook (function_summary::symtab_removal, this);
+  m_symtab_duplication_hook
+    = symtab->add_cgraph_duplication_hook (function_summary::symtab_duplication,
+					   this);
+}
+
+template <typename T>
+void
+function_summary<T *>::release ()
+{
+  if (m_released)
+    return;
+
+  m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook);
+  m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook);
+  m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook);
+
+  /* Release all summaries.  */
+  typedef typename hash_map <map_hash, T *>::iterator map_iterator;
+  for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
+    release ((*it).second);
+
+  m_released = true;
+}
+
+template <typename T>
+void
+function_summary<T *>::release (T *item)
+{
+  if (m_ggc)
+    {
+      item->~T ();
+      ggc_free (item);
+    }
+  else
+    delete item;
+}
+
+template <typename T>
+void
+function_summary<T *>::symtab_insertion (cgraph_node *node, void *data)
+{
+  gcc_checking_assert (node->get_uid ());
+  function_summary *summary = (function_summary <T *> *) (data);
+
+  if (summary->m_insertion_enabled)
+    summary->insert (node, summary->get_create (node));
+}
+
+template <typename T>
+void
+function_summary<T *>::symtab_removal (cgraph_node *node, void *data)
+{
+  gcc_checking_assert (node->get_uid ());
+  function_summary *summary = (function_summary <T *> *) (data);
+
+  int uid = node->get_uid ();
+  T **v = summary->m_map.get (uid);
+
+  if (v)
+    {
+      summary->remove (node, *v);
+
+      if (!summary->m_ggc)
+	delete (*v);
+
+      summary->m_map.remove (uid);
+    }
+}
+
+template <typename T>
+void
+function_summary<T *>::symtab_duplication (cgraph_node *node,
+					   cgraph_node *node2, void *data)
+{
+  function_summary *summary = (function_summary <T *> *) (data);
+  T *v = summary->get (node);
+
+  if (v)
+    {
+      /* This load is necessary, because we insert a new value!  */
+      T *duplicate = summary->allocate_new ();
+      summary->m_map.put (node2->get_uid (), duplicate);
+      summary->duplicate (node, node2, v, duplicate);
+    }
+}
+
+template <typename T>
 void
 gt_ggc_mx(function_summary<T *>* const &summary)
 {
@@ -272,7 +319,8 @@
 public:
   /* Default construction takes SYMTAB as an argument.  */
   call_summary (symbol_table *symtab, bool ggc = false): m_ggc (ggc),
-    m_map (13, ggc), m_released (false), m_symtab (symtab)
+    m_initialize_when_cloning (false), m_map (13, ggc), m_released (false),
+    m_symtab (symtab)
   {
     m_symtab_removal_hook =
       symtab->add_edge_removal_hook
@@ -289,21 +337,7 @@
   }
 
   /* Destruction method that can be called for GGT purpose.  */
-  void release ()
-  {
-    if (m_released)
-      return;
-
-    m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
-    m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
-
-    /* Release all summaries.  */
-    typedef typename hash_map <map_hash, T *>::iterator map_iterator;
-    for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
-      release ((*it).second);
-
-    m_released = true;
-  }
+  void release ();
 
   /* Traverses all summarys with a function F called with
      ARG as argument.  */
@@ -328,21 +362,37 @@
   }
 
   /* Release an item that is stored within map.  */
-  void release (T *item)
+  void release (T *item);
+
+  /* Getter for summary callgraph edge pointer.
+     If a summary for an edge does not exist, it will be created.  */
+  T* get_create (cgraph_edge *edge)
   {
-    if (m_ggc)
-      {
-	item->~T ();
-	ggc_free (item);
-      }
-    else
-      delete item;
+    bool existed;
+    T **v = &m_map.get_or_insert (edge->get_uid (), &existed);
+    if (!existed)
+      *v = allocate_new ();
+
+    return *v;
   }
 
   /* Getter for summary callgraph edge pointer.  */
-  T* get (cgraph_edge *edge)
+  T* get (cgraph_edge *edge) ATTRIBUTE_PURE
   {
-    return get (hashable_uid (edge));
+    T **v = m_map.get (edge->get_uid ());
+    return v == NULL ? NULL : *v;
+  }
+
+  /* Remove edge from summary.  */
+  void remove (cgraph_edge *edge)
+  {
+    int uid = edge->get_uid ();
+    T **v = m_map.get (uid);
+    if (v)
+      {
+	m_map.remove (uid);
+	release (*v);
+      }
   }
 
   /* Return number of elements handled by data structure.  */
@@ -354,67 +404,26 @@
   /* Return true if a summary for the given EDGE already exists.  */
   bool exists (cgraph_edge *edge)
   {
-    return m_map.get (hashable_uid (edge)) != NULL;
+    return m_map.get (edge->get_uid ()) != NULL;
   }
 
   /* Symbol removal hook that is registered to symbol table.  */
-  static void symtab_removal (cgraph_edge *edge, void *data)
-  {
-    call_summary *summary = (call_summary <T *> *) (data);
-
-    int h_uid = summary->hashable_uid (edge);
-    T **v = summary->m_map.get (h_uid);
-
-    if (v)
-      {
-	summary->remove (edge, *v);
-	summary->release (*v);
-	summary->m_map.remove (h_uid);
-      }
-  }
+  static void symtab_removal (cgraph_edge *edge, void *data);
 
   /* Symbol duplication hook that is registered to symbol table.  */
   static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
-				  void *data)
-  {
-    call_summary *summary = (call_summary <T *> *) (data);
-    T **v = summary->m_map.get (summary->hashable_uid (edge1));
-
-    if (v)
-      {
-	/* This load is necessary, because we insert a new value!  */
-	T *data = *v;
-	T *duplicate = summary->allocate_new ();
-	summary->m_map.put (summary->hashable_uid (edge2), duplicate);
-	summary->duplicate (edge1, edge2, data, duplicate);
-      }
-  }
+				  void *data);
 
 protected:
   /* Indication if we use ggc summary.  */
   bool m_ggc;
 
+  /* Initialize summary for an edge that is cloned.  */
+  bool m_initialize_when_cloning;
+
 private:
   typedef int_hash <int, 0, -1> map_hash;
 
-  /* Getter for summary callgraph ID.  */
-  T* get (int uid)
-  {
-    bool existed;
-    T **v = &m_map.get_or_insert (uid, &existed);
-    if (!existed)
-      *v = allocate_new ();
-
-    return *v;
-  }
-
-  /* Get a hashable uid of EDGE.  */
-  int hashable_uid (cgraph_edge *edge)
-  {
-    /* Edge uids start at zero which our hash_map does not like.  */
-    return edge->uid + 1;
-  }
-
   /* Main summary store, where summary ID is used as key.  */
   hash_map <map_hash, T *> m_map;
   /* Internal summary removal hook pointer.  */
@@ -434,6 +443,82 @@
 
 template <typename T>
 void
+call_summary<T *>::release ()
+{
+  if (m_released)
+    return;
+
+  m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
+  m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
+
+  /* Release all summaries.  */
+  typedef typename hash_map <map_hash, T *>::iterator map_iterator;
+  for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
+    release ((*it).second);
+
+  m_released = true;
+}
+
+template <typename T>
+void
+call_summary<T *>::release (T *item)
+{
+  if (m_ggc)
+    {
+      item->~T ();
+      ggc_free (item);
+    }
+  else
+    delete item;
+}
+
+template <typename T>
+void
+call_summary<T *>::symtab_removal (cgraph_edge *edge, void *data)
+{
+  call_summary *summary = (call_summary <T *> *) (data);
+
+  int h_uid = edge->get_uid ();
+  T **v = summary->m_map.get (h_uid);
+
+  if (v)
+    {
+      summary->remove (edge, *v);
+      summary->release (*v);
+      summary->m_map.remove (h_uid);
+    }
+}
+
+template <typename T>
+void
+call_summary<T *>::symtab_duplication (cgraph_edge *edge1,
+				       cgraph_edge *edge2, void *data)
+{
+  call_summary *summary = (call_summary <T *> *) (data);
+  T *edge1_summary = NULL;
+
+  if (summary->m_initialize_when_cloning)
+    edge1_summary = summary->get_create (edge1);
+  else
+    {
+      T **v = summary->m_map.get (edge1->get_uid ());
+      if (v)
+	{
+	  /* This load is necessary, because we insert a new value!  */
+	  edge1_summary = *v;
+	}
+    }
+
+  if (edge1_summary)
+    {
+      T *duplicate = summary->allocate_new ();
+      summary->m_map.put (edge2->get_uid (), duplicate);
+      summary->duplicate (edge1, edge2, edge1_summary, duplicate);
+    }
+}
+
+template <typename T>
+void
 gt_ggc_mx(call_summary<T *>* const &summary)
 {
   gcc_checking_assert (summary->m_ggc);