SOURCES: gcc-pr30052.patch (NEW) - fix mem/time hog.

pluto pluto at pld-linux.org
Sat May 19 16:32:48 CEST 2007


Author: pluto                        Date: Sat May 19 14:32:48 2007 GMT
Module: SOURCES                       Tag: HEAD
---- Log message:
- fix mem/time hog.

---- Files affected:
SOURCES:
   gcc-pr30052.patch (NONE -> 1.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/gcc-pr30052.patch
diff -u /dev/null SOURCES/gcc-pr30052.patch:1.1
--- /dev/null	Sat May 19 16:32:48 2007
+++ SOURCES/gcc-pr30052.patch	Sat May 19 16:32:43 2007
@@ -0,0 +1,4326 @@
+--- gcc42/gcc/pointer-set.c	(revision 124827)
++++ gcc42/gcc/pointer-set.c	(working copy)
+@@ -22,13 +22,12 @@ Boston, MA 02110-1301, USA.  */
+ #include "system.h"
+ #include "pointer-set.h"
+ 
+-/* A pointer sets is represented as a simple open-addressing hash
++/* A pointer set is represented as a simple open-addressing hash
+    table.  Simplifications: The hash code is based on the value of the
+    pointer, not what it points to.  The number of buckets is always a
+    power of 2.  Null pointers are a reserved value.  Deletion is not
+-   supported.  There is no mechanism for user control of hash
+-   function, equality comparison, initial size, or resizing policy.
+-*/
++   supported (yet).  There is no mechanism for user control of hash
++   function, equality comparison, initial size, or resizing policy.  */
+ 
+ struct pointer_set_t
+ {
+@@ -114,22 +113,16 @@ pointer_set_contains (struct pointer_set
+     }
+ }
+ 
+-/* Subroutine of pointer_set_insert.  Inserts P into an empty
+-   element of SLOTS, an array of length N_SLOTS.  Returns nonzero
+-   if P was already present in N_SLOTS.  */
+-static int
++/* Subroutine of pointer_set_insert.  Return the insertion slot for P into
++   an empty element of SLOTS, an array of length N_SLOTS.  */
++static inline size_t
+ insert_aux (void *p, void **slots, size_t n_slots, size_t log_slots)
+ {
+   size_t n = hash1 (p, n_slots, log_slots);
+   while (true)
+     {
+-      if (slots[n] == p)
+-	return 1;
+-      else if (slots[n] == 0)
+-	{
+-	  slots[n] = p;
+-	  return 0;
+-	}
++      if (slots[n] == p || slots[n] == 0)
++	return n;
+       else
+ 	{
+ 	  ++n;
+@@ -144,12 +137,10 @@ insert_aux (void *p, void **slots, size_
+ int
+ pointer_set_insert (struct pointer_set_t *pset, void *p)
+ {
+-  if (insert_aux (p, pset->slots, pset->n_slots, pset->log_slots))
+-    return 1;
+-      
+-  /* We've inserted a new element.  Expand the table if necessary to keep
+-     the load factor small.  */
+-  ++pset->n_elements;
++  size_t n;
++
++  /* For simplicity, expand the set even if P is already there.  This can be
++     superfluous but can happen at most once.  */
+   if (pset->n_elements > pset->n_slots / 4)
+     {
+       size_t new_log_slots = pset->log_slots + 1;
+@@ -158,9 +149,10 @@ pointer_set_insert (struct pointer_set_t
+       size_t i;
+ 
+       for (i = 0; i < pset->n_slots; ++i)
+-	{
+-	  if (pset->slots[i])
+-	    insert_aux (pset->slots[i], new_slots, new_n_slots, new_log_slots);
++        {
++	  void *value = pset->slots[i];
++	  n = insert_aux (value, new_slots, new_n_slots, new_log_slots);
++	  new_slots[n] = value;
+ 	}
+ 
+       XDELETEVEC (pset->slots);
+@@ -169,5 +161,144 @@ pointer_set_insert (struct pointer_set_t
+       pset->slots = new_slots;
+     }
+ 
++  n = insert_aux (p, pset->slots, pset->n_slots, pset->log_slots);
++  if (pset->slots[n])
++    return 1;
++
++  pset->slots[n] = p;
++  ++pset->n_elements;
+   return 0;
+ }
++
++/* Pass each pointer in PSET to the function in FN, together with the fixed
++   parameter DATA.  If FN returns false, the iteration stops.  */
++
++void pointer_set_traverse (struct pointer_set_t *pset,
++			   bool (*fn) (void *, void *), void *data)
++{
++  size_t i;
++  for (i = 0; i < pset->n_slots; ++i)
++    if (pset->slots[i] && !fn (pset->slots[i], data))
++      break;
++}
++
++
++/* A pointer map is represented the same way as a pointer_set, so
++   the hash code is based on the address of the key, rather than
++   its contents.  Null keys are a reserved value.  Deletion is not
++   supported (yet).  There is no mechanism for user control of hash
++   function, equality comparison, initial size, or resizing policy.  */
++
++struct pointer_map_t
++{
++  size_t log_slots;
++  size_t n_slots;		/* n_slots = 2^log_slots */
++  size_t n_elements;
++
++  void **keys;
++  void **values;
++};
++
++/* Allocate an empty pointer map.  */
++struct pointer_map_t *
++pointer_map_create (void)
++{
++  struct pointer_map_t *result = XNEW (struct pointer_map_t);
++
++  result->n_elements = 0;
++  result->log_slots = 8;
++  result->n_slots = (size_t) 1 << result->log_slots;
++
++  result->keys = XCNEWVEC (void *, result->n_slots);
++  result->values = XCNEWVEC (void *, result->n_slots);
++  return result;
++}
++
++/* Reclaims all memory associated with PMAP.  */
++void pointer_map_destroy (struct pointer_map_t *pmap)
++{
++  XDELETEVEC (pmap->keys);
++  XDELETEVEC (pmap->values);
++  XDELETE (pmap);
++}
++
++/* Returns a pointer to the value to which P maps, if PMAP contains P.  P
++   must be nonnull.  Return NULL if PMAP does not contain P.
++
++   Collisions are resolved by linear probing.  */
++void **
++pointer_map_contains (struct pointer_map_t *pmap, void *p)
++{
++  size_t n = hash1 (p, pmap->n_slots, pmap->log_slots);
++
++  while (true)
++    {
++      if (pmap->keys[n] == p)
++	return &pmap->values[n];
++      else if (pmap->keys[n] == 0)
++	return NULL;
++      else
++       {
++         ++n;
++         if (n == pmap->n_slots)
++           n = 0;
++       }
++    }
++}
++
++/* Inserts P into PMAP if it wasn't already there.  Returns a pointer
++   to the value.  P must be nonnull.  */
++void **
++pointer_map_insert (struct pointer_map_t *pmap, void *p)
++{
++  size_t n;
++
++  /* For simplicity, expand the map even if P is already there.  This can be
++     superfluous but can happen at most once.  */
++  if (pmap->n_elements > pmap->n_slots / 4)
++    {
++      size_t new_log_slots = pmap->log_slots + 1;
++      size_t new_n_slots = pmap->n_slots * 2;
++      void **new_keys = XCNEWVEC (void *, new_n_slots);
++      void **new_values = XCNEWVEC (void *, new_n_slots);
++      size_t i;
++
++      for (i = 0; i < pmap->n_slots; ++i)
++	if (pmap->keys[i])
++	  {
++	    void *key = pmap->keys[i];
++	    n = insert_aux (key, new_keys, new_n_slots, new_log_slots);
++	    new_keys[n] = key;
++	    new_values[n] = pmap->values[i];
++	  }
++
++      XDELETEVEC (pmap->keys);
++      XDELETEVEC (pmap->values);
++      pmap->n_slots = new_n_slots;
++      pmap->log_slots = new_log_slots;
++      pmap->keys = new_keys;
++      pmap->values = new_values;
++    }
++
++  n = insert_aux (p, pmap->keys, pmap->n_slots, pmap->log_slots);
++  if (!pmap->keys[n])
++    {
++      ++pmap->n_elements;
++      pmap->keys[n] = p;
++    }
++
++  return &pmap->values[n];
++}
++
++/* Pass each pointer in PMAP to the function in FN, together with the pointer
++   to the value and the fixed parameter DATA.  If FN returns false, the
++   iteration stops.  */
++
++void pointer_map_traverse (struct pointer_map_t *pmap,
++			   bool (*fn) (void *, void **, void *), void *data)
++{
++  size_t i;
++  for (i = 0; i < pmap->n_slots; ++i)
++    if (pmap->keys[i] && !fn (pmap->keys[i], &pmap->values[i], data))
++      break;
++}
+--- gcc42/gcc/pointer-set.h	(revision 124827)
++++ gcc42/gcc/pointer-set.h	(working copy)
+@@ -22,11 +22,21 @@ Software Foundation, 51 Franklin Street,
+ #define POINTER_SET_H
+ 
+ struct pointer_set_t;
+-
+ struct pointer_set_t *pointer_set_create (void);
+ void pointer_set_destroy (struct pointer_set_t *pset);
+ 
+ int pointer_set_contains (struct pointer_set_t *pset, void *p);
+ int pointer_set_insert (struct pointer_set_t *pset, void *p);
++void pointer_set_traverse (struct pointer_set_t *, bool (*) (void *, void *),
++			   void *);
++
++struct pointer_map_t;
++struct pointer_map_t *pointer_map_create (void);
++void pointer_map_destroy (struct pointer_map_t *pmap);
++
++void **pointer_map_contains (struct pointer_map_t *pmap, void *p);
++void **pointer_map_insert (struct pointer_map_t *pmap, void *p);
++void pointer_map_traverse (struct pointer_map_t *,
++			   bool (*) (void *, void **, void *), void *);
+ 
+ #endif  /* POINTER_SET_H  */
+--- gcc42/gcc/Makefile.in	(revision 124827)
++++ gcc42/gcc/Makefile.in	(working copy)
+@@ -1839,7 +1839,7 @@ stor-layout.o : stor-layout.c $(CONFIG_H
+ tree-ssa-structalias.o: tree-ssa-structalias.c tree-ssa-structalias.h \
+    $(SYSTEM_H) $(CONFIG_H) $(GGC_H) $(TREE_H) $(TREE_FLOW_H) \
+    $(TM_H) coretypes.h $(CGRAPH_H) tree-pass.h $(TIMEVAR_H) \
+-   gt-tree-ssa-structalias.h $(PARAMS_H)
++   gt-tree-ssa-structalias.h $(PARAMS_H) pointer-set.h
+ tree-ssa.o : tree-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+    $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) output.h $(DIAGNOSTIC_H) \
+    toplev.h $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
+--- gcc42/gcc/tree-ssa-structalias.c	(revision 124827)
++++ gcc42/gcc/tree-ssa-structalias.c	(working copy)
+@@ -51,10 +51,11 @@ Foundation, Inc., 51 Franklin Street, Fi
+ #include "params.h"
+ #include "tree-ssa-structalias.h"
+ #include "cgraph.h"
++#include "pointer-set.h"
+ 
+ /* The idea behind this analyzer is to generate set constraints from the
+    program, then solve the resulting constraints in order to generate the
+-   points-to sets. 
++   points-to sets.
+ 
+    Set constraints are a way of modeling program analysis problems that
+    involve sets.  They consist of an inclusion constraint language,
+@@ -70,33 +71,33 @@ Foundation, Inc., 51 Franklin Street, Fi
+ 
+    Also see "Ultra-fast Aliasing Analysis using CLA: A Million Lines
+    of C Code in a Second" by ""Nevin Heintze and Olivier Tardieu" at
+-   http://citeseer.ist.psu.edu/heintze01ultrafast.html 
++   http://citeseer.ist.psu.edu/heintze01ultrafast.html
++
++   There are three types of real constraint expressions, DEREF,
++   ADDRESSOF, and SCALAR.  Each constraint expression consists
++   of a constraint type, a variable, and an offset.
+ 
+-   There are three types of constraint expressions, DEREF, ADDRESSOF, and
+-   SCALAR.  Each constraint expression consists of a constraint type,
+-   a variable, and an offset.  
+-   
+    SCALAR is a constraint expression type used to represent x, whether
+    it appears on the LHS or the RHS of a statement.
+    DEREF is a constraint expression type used to represent *x, whether
+-   it appears on the LHS or the RHS of a statement. 
++   it appears on the LHS or the RHS of a statement.
+    ADDRESSOF is a constraint expression used to represent &x, whether
+    it appears on the LHS or the RHS of a statement.
+-   
++
+    Each pointer variable in the program is assigned an integer id, and
+    each field of a structure variable is assigned an integer id as well.
+-   
++
+    Structure variables are linked to their list of fields through a "next
+    field" in each variable that points to the next field in offset
+-   order.  
+-   Each variable for a structure field has 
++   order.
++   Each variable for a structure field has
+ 
+    1. "size", that tells the size in bits of that field.
+    2. "fullsize, that tells the size in bits of the entire structure.
+    3. "offset", that tells the offset in bits from the beginning of the
+    structure to this field.
+ 
+-   Thus, 
++   Thus,
+    struct f
+    {
+      int a;
+@@ -110,50 +111,51 @@ Foundation, Inc., 51 Franklin Street, Fi
+    foo.b -> id 2, size 32, offset 32, fullsize 64, next NULL
+    bar -> id 3, size 32, offset 0, fullsize 32, next NULL
+ 
+-   
++
+   In order to solve the system of set constraints, the following is
+   done:
+ 
+   1. Each constraint variable x has a solution set associated with it,
+   Sol(x).
+-  
++
+   2. Constraints are separated into direct, copy, and complex.
+   Direct constraints are ADDRESSOF constraints that require no extra
+   processing, such as P = &Q
+   Copy constraints are those of the form P = Q.
+-  Complex constraints are all the constraints involving dereferences.
+-  
++  Complex constraints are all the constraints involving dereferences
++  and offsets (including offsetted copies).
++
+   3. All direct constraints of the form P = &Q are processed, such
+-  that Q is added to Sol(P) 
++  that Q is added to Sol(P)
+ 
+   4. All complex constraints for a given constraint variable are stored in a
+-  linked list attached to that variable's node.  
++  linked list attached to that variable's node.
+ 
+   5. A directed graph is built out of the copy constraints. Each
+-  constraint variable is a node in the graph, and an edge from 
++  constraint variable is a node in the graph, and an edge from
+   Q to P is added for each copy constraint of the form P = Q
+-  
++
+   6. The graph is then walked, and solution sets are
+   propagated along the copy edges, such that an edge from Q to P
+   causes Sol(P) <- Sol(P) union Sol(Q).
+-  
++
+   7.  As we visit each node, all complex constraints associated with
+   that node are processed by adding appropriate copy edges to the graph, or the
+-  appropriate variables to the solution set.  
++  appropriate variables to the solution set.
+ 
+   8. The process of walking the graph is iterated until no solution
+   sets change.
+ 
+   Prior to walking the graph in steps 6 and 7, We perform static
+-  cycle elimination on the constraint graph, as well 
++  cycle elimination on the constraint graph, as well
+   as off-line variable substitution.
+-  
++
+   TODO: Adding offsets to pointer-to-structures can be handled (IE not punted
+   on and turned into anything), but isn't.  You can just see what offset
+   inside the pointed-to struct it's going to access.
+-  
++
+   TODO: Constant bounded arrays can be handled as if they were structs of the
+-  same number of elements. 
++  same number of elements.
+ 
+   TODO: Modeling heap and incoming pointers becomes much better if we
+   add fields to them as we discover them, which we could do.
+@@ -161,20 +163,29 @@ Foundation, Inc., 51 Franklin Street, Fi
+   TODO: We could handle unions, but to be honest, it's probably not
+   worth the pain or slowdown.  */
+ 
+-static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) 
+-htab_t heapvar_for_stmt;
++static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) htab_t heapvar_for_stmt;
+ 
+ /* One variable to represent all non-local accesses.  */
+ tree nonlocal_all;
+ 
+ static bool use_field_sensitive = true;
+ static int in_ipa_mode = 0;
++
++/* Used for predecessor bitmaps. */
+ static bitmap_obstack predbitmap_obstack;
+-static bitmap_obstack ptabitmap_obstack;
++
++/* Used for points-to sets.  */
++static bitmap_obstack pta_obstack;
++
++/* Used for oldsolution members of variables. */
++static bitmap_obstack oldpta_obstack;
++
++/* Used for per-solver-iteration bitmaps.  */
+ static bitmap_obstack iteration_obstack;
+ 
+ static unsigned int create_variable_info_for (tree, const char *);
+-static void build_constraint_graph (void);
++typedef struct constraint_graph *constraint_graph_t;
++static void unify_nodes (constraint_graph_t, unsigned int, unsigned int, bool);
+ 
+ DEF_VEC_P(constraint_t);
+ DEF_VEC_ALLOC_P(constraint_t,heap);
+@@ -186,11 +197,13 @@ DEF_VEC_ALLOC_P(constraint_t,heap);
+ static struct constraint_stats
+ {
+   unsigned int total_vars;
+-  unsigned int collapsed_vars;
++  unsigned int nonpointer_vars;
+   unsigned int unified_vars_static;
+   unsigned int unified_vars_dynamic;
+   unsigned int iterations;
+   unsigned int num_edges;
++  unsigned int num_implicit_edges;
++  unsigned int points_to_sets_created;
+ } stats;
+ 
+ struct variable_info
+@@ -205,7 +218,7 @@ struct variable_info
+   tree decl;
+ 
+   /* Offset of this variable, in bits, from the base variable  */
+-  unsigned HOST_WIDE_INT offset;  
++  unsigned HOST_WIDE_INT offset;
+ 
+   /* Size of the variable, in bits.  */
+   unsigned HOST_WIDE_INT size;
+@@ -216,34 +229,21 @@ struct variable_info
+   /* A link to the variable for the next field in this structure.  */
+   struct variable_info *next;
+ 
+-  /* Node in the graph that represents the constraints and points-to
+-     solution for the variable.  */
+-  unsigned int node;
+-
+-  /* True if the address of this variable is taken.  Needed for
+-     variable substitution.  */
+-  unsigned int address_taken:1;
+-
+-  /* True if this variable is the target of a dereference.  Needed for
+-     variable substitution.  */
+-  unsigned int indirect_target:1;
+-  
+   /* True if the variable is directly the target of a dereference.
+      This is used to track which variables are *actually* dereferenced
+-     so we can prune their points to listed. This is equivalent to the
+-     indirect_target flag when no merging of variables happens.  */
++     so we can prune their points to listed. */
+   unsigned int directly_dereferenced:1;
+ 
+   /* True if this is a variable created by the constraint analysis, such as
+      heap variables and constraints we had to break up.  */
+   unsigned int is_artificial_var:1;
+-  
++
+   /* True if this is a special variable whose solution set should not be
+      changed.  */
+   unsigned int is_special_var:1;
+ 
+   /* True for variables whose size is not known or variable.  */
+-  unsigned int is_unknown_size_var:1;  
++  unsigned int is_unknown_size_var:1;
+ 
+   /* True for variables that have unions somewhere in them.  */
+   unsigned int has_union:1;
+@@ -254,16 +254,15 @@ struct variable_info
+   /* Points-to set for this variable.  */
+   bitmap solution;
+ 
++  /* Old points-to set for this variable.  */
++  bitmap oldsolution;
++
+   /* Variable ids represented by this node.  */
+   bitmap variables;
+ 
+-  /* Vector of complex constraints for this node.  Complex
+-     constraints are those involving dereferences.  */
+-  VEC(constraint_t,heap) *complex;
+-  
+-  /* Variable id this was collapsed to due to type unsafety.
+-     This should be unused completely after build_constraint_graph, or
+-     something is broken.  */
++  /* Variable id this was collapsed to due to type unsafety.  This
++     should be unused completely after build_succ_graph, or something
++     is broken.  */
+   struct variable_info *collapsed_to;
+ };
+ typedef struct variable_info *varinfo_t;
+@@ -277,8 +276,8 @@ DEF_VEC_P(varinfo_t);
+ 
+ DEF_VEC_ALLOC_P(varinfo_t, heap);
+ 
+-/* Table of variable info structures for constraint variables.  Indexed directly
+-   by variable info id.  */
++/* Table of variable info structures for constraint variables.
++   Indexed directly by variable info id.  */
+ static VEC(varinfo_t,heap) *varmap;
+ 
+ /* Return the varmap element N */
+@@ -286,7 +285,7 @@ static VEC(varinfo_t,heap) *varmap;
+ static inline varinfo_t
+ get_varinfo (unsigned int n)
+ {
+-  return VEC_index(varinfo_t, varmap, n);
++  return VEC_index (varinfo_t, varmap, n);
+ }
+ 
+ /* Return the varmap element N, following the collapsed_to link.  */
+@@ -294,7 +293,7 @@ get_varinfo (unsigned int n)
+ static inline varinfo_t
+ get_varinfo_fc (unsigned int n)
+ {
+-  varinfo_t v = VEC_index(varinfo_t, varmap, n);
++  varinfo_t v = VEC_index (varinfo_t, varmap, n);
+ 
+   if (v->collapsed_to)
+     return v->collapsed_to;
+@@ -331,10 +330,9 @@ static unsigned int escaped_vars_id;
+ /* Variable that represents non-local variables before we expand it to
+    one for each type.  */
+ static unsigned int nonlocal_vars_id;
+-
+ /* Lookup a heap var for FROM, and return it if we find one.  */
+ 
+-static tree 
++static tree
+ heapvar_lookup (tree from)
+ {
+   struct tree_map *h, in;
+@@ -367,25 +365,21 @@ heapvar_insert (tree from, tree to)
+    named NAME, and using constraint graph node NODE.  */
+ 
+ static varinfo_t
+-new_var_info (tree t, unsigned int id, const char *name, unsigned int node)
++new_var_info (tree t, unsigned int id, const char *name)
+ {
+   varinfo_t ret = pool_alloc (variable_info_pool);
+ 
+   ret->id = id;
+   ret->name = name;
+   ret->decl = t;
+-  ret->node = node;
+-  ret->address_taken = false;
+-  ret->indirect_target = false;
+   ret->directly_dereferenced = false;
+   ret->is_artificial_var = false;
+   ret->is_heap_var = false;
+   ret->is_special_var = false;
+   ret->is_unknown_size_var = false;
+   ret->has_union = false;
+-  ret->solution = BITMAP_ALLOC (&ptabitmap_obstack);
+-  ret->variables = BITMAP_ALLOC (&ptabitmap_obstack);
+-  ret->complex = NULL;
++  ret->solution = BITMAP_ALLOC (&pta_obstack);
++  ret->oldsolution = BITMAP_ALLOC (&oldpta_obstack);
+   ret->next = NULL;
+   ret->collapsed_to = NULL;
+   return ret;
+@@ -395,7 +389,7 @@ typedef enum {SCALAR, DEREF, ADDRESSOF} 
+ 
+ /* An expression that appears in a constraint.  */
+ 
+-struct constraint_expr 
++struct constraint_expr
+ {
+   /* Constraint type.  */
+   constraint_expr_type type;
+@@ -418,7 +412,7 @@ static void get_constraint_for (tree, VE
+ static void do_deref (VEC (ce_s, heap) **);
+ 
+ /* Our set constraints are made up of two constraint expressions, one
+-   LHS, and one RHS.  
++   LHS, and one RHS.
+ 
+    As described in the introduction, our set constraints each represent an
<<Diff was trimmed, longer than 597 lines>>


More information about the pld-cvs-commit mailing list