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