This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC, PATCH 3/n] IPA C++ refactoring


On 08/01/2014 02:34 AM, Trevor Saunders wrote:
>> +++ b/gcc/cgraph.h
>> @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
>>  #include "basic-block.h"
>>  #include "function.h"
>>  #include "ipa-ref.h"
>> +#include "indexed-set.h"
> you don't actually use that here so why are you including it?
>
>> +++ b/gcc/cgraphunit.c
>> @@ -211,11 +211,12 @@ along with GCC; see the file COPYING3.  If not see
>>  #include "tree-nested.h"
>>  #include "gimplify.h"
>>  #include "dbgcnt.h"
>> +#include "indexed-set.h"
> afaict you don't use it here either.
>
>> @@ -529,9 +529,9 @@ cgraph_node::add_new_function (tree fndecl, bool lowered)
>>  	  }
>>  	if (lowered)
>>  	  node->lowered = true;
>> -	if (!cgraph_new_nodes)
>> -	  cgraph_new_nodes = cgraph_node_set_new ();
>> -	cgraph_node_set_add (cgraph_new_nodes, node);
>> +	if (!cgraph_new_nodes.exists ())
>> +	  cgraph_new_nodes.create (4);
> I don't think you need this, if the vector doesn't exist it will point
> at null, and safe_push knows how to handle that.
>
>> +++ b/gcc/indexed-set.h
>> +template<typename T>
>> +class indexed_set
> per below I don't think you actually need this class after all.
>
>> +{
>> +public:
>> +  class iterator
>> +  {
>> +  public:
>> +    iterator (const vec<T> *v, unsigned index) : m_index (index), m_vector (v) {};
>> +
>> +    inline T operator * ()
>> +    {
>> +      gcc_assert (m_index < m_vector->length ());
>> +
>> +      return (*m_vector)[m_index];
>> +    }
>> +
>> +    inline iterator &operator ++ ()
>> +    {
>> +      m_index++;
>> +      return *this;
>> +    }
>> +
>> +    bool operator != (const iterator &other) const
>> +    {
>> +      return m_vector != other.m_vector || m_index != other.m_index;
>> +    }
>> +
>> +    inline int
>> +    get_index (void) const
>> +    {
>> +      return m_index;
>> +    }
>> +
>> +  private:
>> +    unsigned m_index;
>> +    const vec <T> *m_vector;
>> +  };
>> +
>> +  /* Iterator to the start of data structure.  */
>> +
>> +  iterator begin () const
>> +  {
>> +    gcc_assert (!is_empty ());
> it seems to me it would be better to just return the iterator for end ()
> if there's no elements.
>
>> +
>> +    iterator iter (&m_vector, 0);
>> +    return iter;
>> +  }
>> +
>> +  /* Iterator to the end of data structure.  */
>> +
>> +  iterator end () const
>> +  {
>> +    return iterator (&m_vector, m_vector.length ());
>> +  }
>> +
>> +  /* Add item V to data structure.  */
>> +
>> +  inline void
> afaik defining within the class implies inline.
>
>> +  add (T v)
>  You are passing by value here, which you probably don't want to do if T
>  is big.
>
>> +  {
>> +    m_map.put (v, m_vector.length ());
>> +    m_vector.safe_push (v);
> I think this blows up if v was already in the map, so assert it isn't?
>
>> +  }
>> +
>> +  /* Return iterator for an item V.  */
>> +
>> +  inline iterator
>> +  find (T v)
>> +  {
>> +    int *item = m_map.get (v);
>> +    gcc_unreachable ();
>> +
>> +    return item ?  iterator (&m_vector, *item) : end ();
> returning an iterator here seems silly, the only information you get is
> the index and if the element exists in the map, so just return an int?
>
>> +  }
>> +
>> +  /* Return if the data structure is empty.  */
>> +
>> +  inline bool
>> +  is_empty (void) const
>> +  {
>> +    return m_vector.is_empty ();
>> +  }
>> +
>> +  /* Return number of items stored in data structure.  */
>> +
>> +  inline unsigned
>> +  length (void)
>> +  {
>> +    return m_vector.length ();
>> +  }
>> +
>> +
>> +private:
>> +  hash_map<T, int> m_map;
>> +  auto_vec<T> m_vector;
> I know you don't use this with anything but pointers now, but this will
> do "weird" things if T is some sort of object.
>
>> +};
>> +
>> +#endif
>> diff --git a/gcc/tree-emutls.c b/gcc/tree-emutls.c
>> index 89197c7..9c06aec 100644
>> --- a/gcc/tree-emutls.c
>> +++ b/gcc/tree-emutls.c
>> @@ -42,6 +42,7 @@ along with GCC; see the file COPYING3.  If not see
>>  #include "target.h"
>>  #include "targhooks.h"
>>  #include "tree-iterator.h"
>> +#include "indexed-set.h"
>>  
>>  
>>  /* Whenever a target does not support thread-local storage (TLS) natively,
>> @@ -70,7 +71,7 @@ along with GCC; see the file COPYING3.  If not see
>>  /* These two vectors, once fully populated, are kept in lock-step so that
>>     the index of a TLS variable equals the index of its control variable in
>>     the other vector.  */
>> -static varpool_node_set tls_vars;
>> +static indexed_set<varpool_node *> tls_vars;
> Note that will create a static initializer that calls malloc, and tls
> emulation probably isn't needed on many targets, so I'd guess your
> better off using a hash_map * with new and delete as annoying as that is.
>
>>  static vec<varpool_node *> control_vars;
> so, looking at this thing more closely it looks like this is just a
> weirdo implementation of a hash map from varpool_node * to (varpool_node
> *, tree) so I think you could just do
>
> struct tls_var_data
> {
>   varpool_node *control_var;
>   tree access;
> };
>
> hash_map<var_pool_node *, tls_var_data>
>
> Thanks!
>
> Trev
>
Hello,
   I followed Trevor's advice and indexed_set won't be needed.

There's a new patch that utilizes just sent hash_map modification (hash_map::traverse can modify values).
Regtested on x86_64-pc-linux-gnu with --enable-tls=no.

Thanks,
Martin

Attachment: symtab-node-removal.changelog
Description: Text document

diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index d8651e2..edf3f7f 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -1200,41 +1200,6 @@ public:
   unsigned calls_comdat_local : 1;
 };
 
-/* A cgraph node set is a collection of cgraph nodes.  A cgraph node
-   can appear in multiple sets.  */
-struct cgraph_node_set_def
-{
-  struct pointer_map_t *map;
-  vec<cgraph_node *> nodes;
-};
-
-typedef cgraph_node_set_def *cgraph_node_set;
-typedef struct varpool_node_set_def *varpool_node_set;
-
-class varpool_node;
-
-/* A varpool node set is a collection of varpool nodes.  A varpool node
-   can appear in multiple sets.  */
-struct varpool_node_set_def
-{
-  struct pointer_map_t * map;
-  vec<varpool_node *> nodes;
-};
-
-/* Iterator structure for cgraph node sets.  */
-struct cgraph_node_set_iterator
-{
-  cgraph_node_set set;
-  unsigned index;
-};
-
-/* Iterator structure for varpool node sets.  */
-struct varpool_node_set_iterator
-{
-  varpool_node_set set;
-  unsigned index;
-};
-
 /* Structure containing additional information about an indirect call.  */
 
 struct GTY(()) cgraph_indirect_call_info
@@ -1509,7 +1474,7 @@ enum cgraph_state
 };
 extern enum cgraph_state cgraph_state;
 extern bool cgraph_function_flags_ready;
-extern cgraph_node_set cgraph_new_nodes;
+extern vec<cgraph_node *> cgraph_new_nodes;
 
 extern GTY(()) struct asm_node *asm_nodes;
 extern GTY(()) int symtab_order;
@@ -1615,24 +1580,7 @@ void record_references_in_initializer (tree, bool);
 
 /* In ipa.c  */
 bool symtab_remove_unreachable_nodes (bool, FILE *);
-cgraph_node_set cgraph_node_set_new (void);
-cgraph_node_set_iterator cgraph_node_set_find (cgraph_node_set,
-					       cgraph_node *);
-void cgraph_node_set_add (cgraph_node_set, cgraph_node *);
-void cgraph_node_set_remove (cgraph_node_set, cgraph_node *);
-void dump_cgraph_node_set (FILE *, cgraph_node_set);
-void debug_cgraph_node_set (cgraph_node_set);
-void free_cgraph_node_set (cgraph_node_set);
 void cgraph_build_static_cdtor (char which, tree body, int priority);
-
-varpool_node_set varpool_node_set_new (void);
-varpool_node_set_iterator varpool_node_set_find (varpool_node_set,
-						 varpool_node *);
-void varpool_node_set_add (varpool_node_set, varpool_node *);
-void varpool_node_set_remove (varpool_node_set, varpool_node *);
-void dump_varpool_node_set (FILE *, varpool_node_set);
-void debug_varpool_node_set (varpool_node_set);
-void free_varpool_node_set (varpool_node_set);
 void ipa_discover_readonly_nonaddressable_vars (void);
 
 /* In predict.c  */
@@ -1948,93 +1896,6 @@ cgraph_next_function_with_gimple_body (cgraph_node *node)
 /* Create a new static variable of type TYPE.  */
 tree add_new_static_var (tree type);
 
-/* Return true if iterator CSI points to nothing.  */
-static inline bool
-csi_end_p (cgraph_node_set_iterator csi)
-{
-  return csi.index >= csi.set->nodes.length ();
-}
-
-/* Advance iterator CSI.  */
-static inline void
-csi_next (cgraph_node_set_iterator *csi)
-{
-  csi->index++;
-}
-
-/* Return the node pointed to by CSI.  */
-static inline cgraph_node *
-csi_node (cgraph_node_set_iterator csi)
-{
-  return csi.set->nodes[csi.index];
-}
-
-/* Return an iterator to the first node in SET.  */
-static inline cgraph_node_set_iterator
-csi_start (cgraph_node_set set)
-{
-  cgraph_node_set_iterator csi;
-
-  csi.set = set;
-  csi.index = 0;
-  return csi;
-}
-
-/* Return true if SET contains NODE.  */
-static inline bool
-cgraph_node_in_set_p (cgraph_node *node, cgraph_node_set set)
-{
-  cgraph_node_set_iterator csi;
-  csi = cgraph_node_set_find (set, node);
-  return !csi_end_p (csi);
-}
-
-/* Return number of nodes in SET.  */
-static inline size_t
-cgraph_node_set_size (cgraph_node_set set)
-{
-  return set->nodes.length ();
-}
-
-/* Return true if iterator VSI points to nothing.  */
-static inline bool
-vsi_end_p (varpool_node_set_iterator vsi)
-{
-  return vsi.index >= vsi.set->nodes.length ();
-}
-
-/* Advance iterator VSI.  */
-static inline void
-vsi_next (varpool_node_set_iterator *vsi)
-{
-  vsi->index++;
-}
-
-/* Return the node pointed to by VSI.  */
-static inline varpool_node *
-vsi_node (varpool_node_set_iterator vsi)
-{
-  return vsi.set->nodes[vsi.index];
-}
-
-/* Return an iterator to the first node in SET.  */
-static inline varpool_node_set_iterator
-vsi_start (varpool_node_set set)
-{
-  varpool_node_set_iterator vsi;
-
-  vsi.set = set;
-  vsi.index = 0;
-  return vsi;
-}
-
-/* Return number of nodes in SET.  */
-static inline size_t
-varpool_node_set_size (varpool_node_set set)
-{
-  return set->nodes.length ();
-}
-
 /* Uniquize all constants that appear in memory.
    Each constant in memory thus far output is recorded
    in `const_desc_table'.  */
@@ -2052,20 +1913,6 @@ struct GTY(()) constant_descriptor_tree {
   hashval_t hash;
 };
 
-/* Return true if set is nonempty.  */
-static inline bool
-cgraph_node_set_nonempty_p (cgraph_node_set set)
-{
-  return !set->nodes.is_empty ();
-}
-
-/* Return true if set is nonempty.  */
-static inline bool
-varpool_node_set_nonempty_p (varpool_node_set set)
-{
-  return !set->nodes.is_empty ();
-}
-
 /* Return true when function is only called directly or it has alias.
    i.e. it is not externally visible, address was not taken and
    it is not used in any other non-standard way.  */
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 02c9fa1..a07adbf 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -215,7 +215,7 @@ along with GCC; see the file COPYING3.  If not see
 /* Queue of cgraph nodes scheduled to be added into cgraph.  This is a
    secondary queue used during optimization to accommodate passes that
    may generate new functions that need to be optimized and expanded.  */
-cgraph_node_set cgraph_new_nodes;
+vec<cgraph_node *> cgraph_new_nodes;
 
 static void expand_all_functions (void);
 static void mark_functions_to_output (void);
@@ -300,17 +300,16 @@ void
 cgraph_process_new_functions (void)
 {
   tree fndecl;
-  struct cgraph_node *node;
-  cgraph_node_set_iterator csi;
 
-  if (!cgraph_new_nodes)
+  if (!cgraph_new_nodes.exists ())
     return;
+
   handle_alias_pairs ();
   /*  Note that this queue may grow as its being processed, as the new
       functions may generate new ones.  */
-  for (csi = csi_start (cgraph_new_nodes); !csi_end_p (csi); csi_next (&csi))
+  for (unsigned i = 0; i < cgraph_new_nodes.length (); i++)
     {
-      node = csi_node (csi);
+      cgraph_node *node = cgraph_new_nodes[i];
       fndecl = node->decl;
       switch (cgraph_state)
 	{
@@ -357,8 +356,8 @@ cgraph_process_new_functions (void)
 	  break;
 	}
     }
-  free_cgraph_node_set (cgraph_new_nodes);
-  cgraph_new_nodes = NULL;
+
+    cgraph_new_nodes.release ();
 }
 
 /* As an GCC extension we allow redefinition of the function.  The
@@ -501,9 +500,7 @@ cgraph_node::add_new_function (tree fndecl, bool lowered)
 	node = cgraph_node::get_create (fndecl);
 	if (lowered)
 	  node->lowered = true;
-	if (!cgraph_new_nodes)
-	  cgraph_new_nodes = cgraph_node_set_new ();
-	cgraph_node_set_add (cgraph_new_nodes, node);
+	cgraph_new_nodes.safe_push (node);
         break;
 
       case CGRAPH_STATE_IPA:
@@ -529,9 +526,7 @@ cgraph_node::add_new_function (tree fndecl, bool lowered)
 	  }
 	if (lowered)
 	  node->lowered = true;
-	if (!cgraph_new_nodes)
-	  cgraph_new_nodes = cgraph_node_set_new ();
-	cgraph_node_set_add (cgraph_new_nodes, node);
+	cgraph_new_nodes.safe_push (node);
         break;
 
       case CGRAPH_STATE_FINISHED:
diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c
index 5924140..2ddd029 100644
--- a/gcc/ipa-inline-transform.c
+++ b/gcc/ipa-inline-transform.c
@@ -96,7 +96,7 @@ can_remove_node_now_p_1 (struct cgraph_node *node)
 	  && !DECL_VIRTUAL_P (node->decl)
 	  /* During early inlining some unanalyzed cgraph nodes might be in the
 	     callgraph and they might reffer the function in question.  */
-	  && !cgraph_new_nodes);
+	  && !cgraph_new_nodes.exists ());
 }
 
 /* We are going to eliminate last direct call to NODE (or alias of it) via edge E.
diff --git a/gcc/ipa-utils.c b/gcc/ipa-utils.c
index 482fc22..64ede27 100644
--- a/gcc/ipa-utils.c
+++ b/gcc/ipa-utils.c
@@ -380,265 +380,6 @@ get_base_var (tree t)
   return t;
 }
 
-
-/* Create a new cgraph node set.  */
-
-cgraph_node_set
-cgraph_node_set_new (void)
-{
-  cgraph_node_set new_node_set;
-
-  new_node_set = XCNEW (struct cgraph_node_set_def);
-  new_node_set->map = pointer_map_create ();
-  new_node_set->nodes.create (0);
-  return new_node_set;
-}
-
-
-/* Add cgraph_node NODE to cgraph_node_set SET.  */
-
-void
-cgraph_node_set_add (cgraph_node_set set, struct cgraph_node *node)
-{
-  void **slot;
-
-  slot = pointer_map_insert (set->map, node);
-
-  if (*slot)
-    {
-      int index = (size_t) *slot - 1;
-      gcc_checking_assert ((set->nodes[index]
-		           == node));
-      return;
-    }
-
-  *slot = (void *)(size_t) (set->nodes.length () + 1);
-
-  /* Insert into node vector.  */
-  set->nodes.safe_push (node);
-}
-
-
-/* Remove cgraph_node NODE from cgraph_node_set SET.  */
-
-void
-cgraph_node_set_remove (cgraph_node_set set, struct cgraph_node *node)
-{
-  void **slot, **last_slot;
-  int index;
-  struct cgraph_node *last_node;
-
-  slot = pointer_map_contains (set->map, node);
-  if (slot == NULL || !*slot)
-    return;
-
-  index = (size_t) *slot - 1;
-  gcc_checking_assert (set->nodes[index]
-	      	       == node);
-
-  /* Remove from vector. We do this by swapping node with the last element
-     of the vector.  */
-  last_node = set->nodes.pop ();
-  if (last_node != node)
-    {
-      last_slot = pointer_map_contains (set->map, last_node);
-      gcc_checking_assert (last_slot && *last_slot);
-      *last_slot = (void *)(size_t) (index + 1);
-
-      /* Move the last element to the original spot of NODE.  */
-      set->nodes[index] = last_node;
-    }
-
-  /* Remove element from hash table.  */
-  *slot = NULL;
-}
-
-
-/* Find NODE in SET and return an iterator to it if found.  A null iterator
-   is returned if NODE is not in SET.  */
-
-cgraph_node_set_iterator
-cgraph_node_set_find (cgraph_node_set set, struct cgraph_node *node)
-{
-  void **slot;
-  cgraph_node_set_iterator csi;
-
-  slot = pointer_map_contains (set->map, node);
-  if (slot == NULL || !*slot)
-    csi.index = (unsigned) ~0;
-  else
-    csi.index = (size_t)*slot - 1;
-  csi.set = set;
-
-  return csi;
-}
-
-
-/* Dump content of SET to file F.  */
-
-void
-dump_cgraph_node_set (FILE *f, cgraph_node_set set)
-{
-  cgraph_node_set_iterator iter;
-
-  for (iter = csi_start (set); !csi_end_p (iter); csi_next (&iter))
-    {
-      struct cgraph_node *node = csi_node (iter);
-      fprintf (f, " %s/%i", node->name (), node->order);
-    }
-  fprintf (f, "\n");
-}
-
-
-/* Dump content of SET to stderr.  */
-
-DEBUG_FUNCTION void
-debug_cgraph_node_set (cgraph_node_set set)
-{
-  dump_cgraph_node_set (stderr, set);
-}
-
-
-/* Free varpool node set.  */
-
-void
-free_cgraph_node_set (cgraph_node_set set)
-{
-  set->nodes.release ();
-  pointer_map_destroy (set->map);
-  free (set);
-}
-
-
-/* Create a new varpool node set.  */
-
-varpool_node_set
-varpool_node_set_new (void)
-{
-  varpool_node_set new_node_set;
-
-  new_node_set = XCNEW (struct varpool_node_set_def);
-  new_node_set->map = pointer_map_create ();
-  new_node_set->nodes.create (0);
-  return new_node_set;
-}
-
-
-/* Add varpool_node NODE to varpool_node_set SET.  */
-
-void
-varpool_node_set_add (varpool_node_set set, varpool_node *node)
-{
-  void **slot;
-
-  slot = pointer_map_insert (set->map, node);
-
-  if (*slot)
-    {
-      int index = (size_t) *slot - 1;
-      gcc_checking_assert ((set->nodes[index]
-		           == node));
-      return;
-    }
-
-  *slot = (void *)(size_t) (set->nodes.length () + 1);
-
-  /* Insert into node vector.  */
-  set->nodes.safe_push (node);
-}
-
-
-/* Remove varpool_node NODE from varpool_node_set SET.  */
-
-void
-varpool_node_set_remove (varpool_node_set set, varpool_node *node)
-{
-  void **slot, **last_slot;
-  int index;
-  varpool_node *last_node;
-
-  slot = pointer_map_contains (set->map, node);
-  if (slot == NULL || !*slot)
-    return;
-
-  index = (size_t) *slot - 1;
-  gcc_checking_assert (set->nodes[index]
-	      	       == node);
-
-  /* Remove from vector. We do this by swapping node with the last element
-     of the vector.  */
-  last_node = set->nodes.pop ();
-  if (last_node != node)
-    {
-      last_slot = pointer_map_contains (set->map, last_node);
-      gcc_checking_assert (last_slot && *last_slot);
-      *last_slot = (void *)(size_t) (index + 1);
-
-      /* Move the last element to the original spot of NODE.  */
-      set->nodes[index] = last_node;
-    }
-
-  /* Remove element from hash table.  */
-  *slot = NULL;
-}
-
-
-/* Find NODE in SET and return an iterator to it if found.  A null iterator
-   is returned if NODE is not in SET.  */
-
-varpool_node_set_iterator
-varpool_node_set_find (varpool_node_set set, varpool_node *node)
-{
-  void **slot;
-  varpool_node_set_iterator vsi;
-
-  slot = pointer_map_contains (set->map, node);
-  if (slot == NULL || !*slot)
-    vsi.index = (unsigned) ~0;
-  else
-    vsi.index = (size_t)*slot - 1;
-  vsi.set = set;
-
-  return vsi;
-}
-
-
-/* Dump content of SET to file F.  */
-
-void
-dump_varpool_node_set (FILE *f, varpool_node_set set)
-{
-  varpool_node_set_iterator iter;
-
-  for (iter = vsi_start (set); !vsi_end_p (iter); vsi_next (&iter))
-    {
-      varpool_node *node = vsi_node (iter);
-      fprintf (f, " %s", node->name ());
-    }
-  fprintf (f, "\n");
-}
-
-
-/* Free varpool node set.  */
-
-void
-free_varpool_node_set (varpool_node_set set)
-{
-  set->nodes.release ();
-  pointer_map_destroy (set->map);
-  free (set);
-}
-
-
-/* Dump content of SET to stderr.  */
-
-DEBUG_FUNCTION void
-debug_varpool_node_set (varpool_node_set set)
-{
-  dump_varpool_node_set (stderr, set);
-}
-
-
 /* SRC and DST are going to be merged.  Take SRC's profile and merge it into
    DST so it is not going to be lost.  Destroy SRC's body on the way.  */
 
diff --git a/gcc/tree-emutls.c b/gcc/tree-emutls.c
index 89197c7..2c9cfe4 100644
--- a/gcc/tree-emutls.c
+++ b/gcc/tree-emutls.c
@@ -42,7 +42,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "target.h"
 #include "targhooks.h"
 #include "tree-iterator.h"
-
+#include "hash-map.h"
 
 /* Whenever a target does not support thread-local storage (TLS) natively,
    we can emulate it with some run-time support in libgcc.  This will in
@@ -67,15 +67,17 @@ along with GCC; see the file COPYING3.  If not see
    to the symbol table early in the GIMPLE optimization path, before we
    write things out to LTO intermediate files.  */
 
-/* These two vectors, once fully populated, are kept in lock-step so that
-   the index of a TLS variable equals the index of its control variable in
-   the other vector.  */
-static varpool_node_set tls_vars;
-static vec<varpool_node *> control_vars;
+/* Value for TLS varpool node where a pointer to control variable and
+   access variable are stored. */
+struct tls_var_data
+{
+  varpool_node *control_var;
+  tree access;
+};
 
-/* For the current basic block, an SSA_NAME that has computed the address 
-   of the TLS variable at the corresponding index.  */
-static vec<tree> access_vars;
+/* TLS map accesses mapping between a TLS varpool node and a pair
+   made by control variable and access variable.  */
+static hash_map<varpool_node *, tls_var_data> *tls_map = NULL;
 
 /* The type of the control structure, shared with the emutls.c runtime.  */
 static tree emutls_object_type;
@@ -350,33 +352,6 @@ new_emutls_decl (tree decl, tree alias_of)
   return to;
 }
 
-/* Look up the index of the TLS variable DECL.  This index can then be
-   used in both the control_vars and access_vars arrays.  */
-
-static unsigned int
-emutls_index (tree decl)
-{
-  varpool_node_set_iterator i;
-  
-  i = varpool_node_set_find (tls_vars, varpool_node::get (decl));
-  gcc_assert (i.index != ~0u);
-
-  return i.index;
-}
-
-/* Look up the control variable for the TLS variable DECL.  */
-
-static tree
-emutls_decl (tree decl)
-{
-  varpool_node *var;
-  unsigned int i;
-
-  i = emutls_index (decl);
-  var = control_vars[i];
-  return var->decl;
-}
-
 /* Generate a call statement to initialize CONTROL_DECL for TLS_DECL.
    This only needs to happen for TLS COMMON variables; non-COMMON
    variables can be initialized statically.  Insert the generated
@@ -423,19 +398,17 @@ struct lower_emutls_data
 static tree
 gen_emutls_addr (tree decl, struct lower_emutls_data *d)
 {
-  unsigned int index;
-  tree addr;
-
   /* Compute the address of the TLS variable with help from runtime.  */
-  index = emutls_index (decl);
-  addr = access_vars[index];
+  tls_var_data *data = tls_map->get (varpool_node::get (decl));
+  tree addr = data->access;
+
   if (addr == NULL)
     {
       varpool_node *cvar;
       tree cdecl;
       gimple x;
 
-      cvar = control_vars[index];
+      cvar = data->control_var;
       cdecl = cvar->decl;
       TREE_ADDRESSABLE (cdecl) = 1;
 
@@ -455,7 +428,7 @@ gen_emutls_addr (tree decl, struct lower_emutls_data *d)
       d->cfun_node->add_reference (cvar, IPA_REF_ADDR, x);
 
       /* Record this ssa_name for possible use later in the basic block.  */
-      access_vars[index] = addr;
+      data->access = addr;
     }
 
   return addr;
@@ -608,13 +581,20 @@ lower_emutls_phi_arg (gimple phi, unsigned int i, struct lower_emutls_data *d)
     }
 }
 
+bool
+reset_access (varpool_node * const &, tls_var_data *data, void *)
+{
+  data->access = NULL;
+
+  return true;
+}
+
 /* Clear the ACCESS_VARS array, in order to begin a new block.  */
 
 static inline void
 clear_access_vars (void)
 {
-  memset (access_vars.address (), 0,
-          access_vars.length () * sizeof (tree));
+  tls_map->traverse<void *, reset_access> (NULL);
 }
 
 /* Lower the entire function NODE.  */
@@ -705,14 +685,13 @@ static bool
 create_emultls_var (varpool_node *var, void *data)
 {
   tree cdecl;
-  varpool_node *cvar;
+  tls_var_data value;
 
   cdecl = new_emutls_decl (var->decl,
 			   var->alias && var->analyzed
 			   ? var->get_alias_target ()->decl : NULL);
 
-  cvar = varpool_node::get (cdecl);
-  control_vars.quick_push (cvar);
+  varpool_node *cvar = varpool_node::get (cdecl);
 
   if (!var->alias)
     {
@@ -730,6 +709,10 @@ create_emultls_var (varpool_node *var, void *data)
      which is special-cased inside the DWARF2 output routines.  */
   SET_DECL_VALUE_EXPR (var->decl, cdecl);
   DECL_HAS_VALUE_EXPR_P (var->decl) = 1;
+
+  value.control_var = cvar;
+  tls_map->put (var, value);
+
   return false;
 }
 
@@ -739,12 +722,11 @@ static unsigned int
 ipa_lower_emutls (void)
 {
   varpool_node *var;
-  struct cgraph_node *func;
+  cgraph_node *func;
   bool any_aliases = false;
   tree ctor_body = NULL;
-  unsigned int i, n_tls;
 
-  tls_vars = varpool_node_set_new ();
+  auto_vec <varpool_node *> tls_vars;
 
   /* Examine all global variables for TLS variables.  */
   FOR_EACH_VARIABLE (var)
@@ -752,30 +734,25 @@ ipa_lower_emutls (void)
       {
 	gcc_checking_assert (TREE_STATIC (var->decl)
 			     || DECL_EXTERNAL (var->decl));
-	varpool_node_set_add (tls_vars, var);
+	tls_vars.safe_push (var);
 	if (var->alias && var->definition)
-	  varpool_node_set_add (tls_vars, var->ultimate_alias_target ());
+	  tls_vars.safe_push (var->ultimate_alias_target ());
       }
 
   /* If we found no TLS variables, then there is no further work to do.  */
-  if (!tls_vars->nodes.exists ())
+  if (tls_vars.is_empty ())
     {
-      tls_vars = NULL;
       if (dump_file)
 	fprintf (dump_file, "No TLS variables found.\n");
       return 0;
     }
 
-  /* Allocate the on-the-side arrays that share indicies with the TLS vars.  */
-  n_tls = tls_vars->nodes.length ();
-  control_vars.create (n_tls);
-  access_vars.create (n_tls);
-  access_vars.safe_grow_cleared (n_tls);
+  tls_map = new hash_map <varpool_node *, tls_var_data> ();
 
   /* Create the control variables for each TLS variable.  */
-  FOR_EACH_VEC_ELT (tls_vars->nodes, i, var)
+  for (unsigned i = 0; i < tls_vars.length (); i++)
     {
-      var = tls_vars->nodes[i];
+      var = tls_vars[i];
 
       if (var->alias && !var->analyzed)
 	any_aliases = true;
@@ -787,10 +764,12 @@ ipa_lower_emutls (void)
   if (any_aliases)
     {
       alias_pair *p;
+      unsigned int i;
       FOR_EACH_VEC_SAFE_ELT (alias_pairs, i, p)
 	if (DECL_THREAD_LOCAL_P (p->decl))
 	  {
-	    p->decl = emutls_decl (p->decl);
+	    p->decl = tls_map->get
+	      (varpool_node::get (p->decl))->control_var->decl;
 	    p->target = get_emutls_object_name (p->target);
 	  }
     }
@@ -804,9 +783,7 @@ ipa_lower_emutls (void)
   if (ctor_body)
     cgraph_build_static_cdtor ('I', ctor_body, DEFAULT_INIT_PRIORITY);
 
-  control_vars.release ();
-  access_vars.release ();
-  free_varpool_node_set (tls_vars);
+  delete tls_map;
 
   return 0;
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]