pointer-set.h (struct pointer_set_t): Move here from pointer-set.c.

2013-06-24  Richard Biener  <rguenther@suse.de>

	* pointer-set.h (struct pointer_set_t): Move here from
	pointer-set.c.
	(pointer_set_lookup): Declare.
	(class pointer_map): New template class implementing a
	generic pointer to T map.
	(pointer_map<T>::pointer_map, pointer_map<T>::~pointer_map,
	pointer_map<T>::contains, pointer_map<T>::insert,
	pointer_map<T>::traverse): New functions.
	* pointer-set.c (struct pointer_set_t): Moved to pointer-set.h.
	(pointer_set_lookup): New function.
	(pointer_set_contains): Use pointer_set_lookup.
	(pointer_set_insert): Likewise.
	(insert_aux): Remove.
	(struct pointer_map_t): Embed a pointer_set_t.
	(pointer_map_create): Adjust.
	(pointer_map_destroy): Likewise.
	(pointer_map_contains): Likewise.
	(pointer_map_insert): Likewise.
	(pointer_map_traverse): Likewise.
	* tree-streamer.h (struct streamer_tree_cache_d): Use a
	pointer_map<unsigned> instead of a pointer_map_t.
	* tree-streamer.c (streamer_tree_cache_insert_1): Adjust.
	(streamer_tree_cache_lookup): Likewise.
	(streamer_tree_cache_create): Likewise.
	(streamer_tree_cache_delete): Likewise.
	* lto-streamer.h (struct lto_tree_ref_encoder): Use a
	pointer_map<unsigned> instead of a pointer_map_t.
	(lto_init_tree_ref_encoder): Adjust.
	(lto_destroy_tree_ref_encoder): Likewise.
	* lto-section-out.c (lto_output_decl_index): Likewise.
	(lto_record_function_out_decl_state): Likewise.
	* dominance.c (iterate_fix_dominators): Use pointer_map<int>.

From-SVN: r200367
This commit is contained in:
Richard Biener 2013-06-24 12:17:16 +00:00 committed by Richard Biener
parent e04518ae25
commit 7c5848b899
8 changed files with 266 additions and 140 deletions

View File

@ -1,3 +1,38 @@
2013-06-24 Richard Biener <rguenther@suse.de>
* pointer-set.h (struct pointer_set_t): Move here from
pointer-set.c.
(pointer_set_lookup): Declare.
(class pointer_map): New template class implementing a
generic pointer to T map.
(pointer_map<T>::pointer_map, pointer_map<T>::~pointer_map,
pointer_map<T>::contains, pointer_map<T>::insert,
pointer_map<T>::traverse): New functions.
* pointer-set.c (struct pointer_set_t): Moved to pointer-set.h.
(pointer_set_lookup): New function.
(pointer_set_contains): Use pointer_set_lookup.
(pointer_set_insert): Likewise.
(insert_aux): Remove.
(struct pointer_map_t): Embed a pointer_set_t.
(pointer_map_create): Adjust.
(pointer_map_destroy): Likewise.
(pointer_map_contains): Likewise.
(pointer_map_insert): Likewise.
(pointer_map_traverse): Likewise.
* tree-streamer.h (struct streamer_tree_cache_d): Use a
pointer_map<unsigned> instead of a pointer_map_t.
* tree-streamer.c (streamer_tree_cache_insert_1): Adjust.
(streamer_tree_cache_lookup): Likewise.
(streamer_tree_cache_create): Likewise.
(streamer_tree_cache_delete): Likewise.
* lto-streamer.h (struct lto_tree_ref_encoder): Use a
pointer_map<unsigned> instead of a pointer_map_t.
(lto_init_tree_ref_encoder): Adjust.
(lto_destroy_tree_ref_encoder): Likewise.
* lto-section-out.c (lto_output_decl_index): Likewise.
(lto_record_function_out_decl_state): Likewise.
* dominance.c (iterate_fix_dominators): Use pointer_map<int>.
2013-06-24 Richard Biener <rguenther@suse.de>
PR tree-optimization/57488

View File

@ -1248,7 +1248,7 @@ iterate_fix_dominators (enum cdi_direction dir, vec<basic_block> bbs,
size_t dom_i;
edge e;
edge_iterator ei;
struct pointer_map_t *map;
pointer_map<int> *map;
int *parent, *son, *brother;
unsigned int dir_index = dom_convert_dir_to_idx (dir);
@ -1336,15 +1336,15 @@ iterate_fix_dominators (enum cdi_direction dir, vec<basic_block> bbs,
}
/* Construct the graph G. */
map = pointer_map_create ();
map = new pointer_map<int>;
FOR_EACH_VEC_ELT (bbs, i, bb)
{
/* If the dominance tree is conservatively correct, split it now. */
if (conservative)
set_immediate_dominator (CDI_DOMINATORS, bb, NULL);
*pointer_map_insert (map, bb) = (void *) (size_t) i;
*map->insert (bb) = i;
}
*pointer_map_insert (map, ENTRY_BLOCK_PTR) = (void *) (size_t) n;
*map->insert (ENTRY_BLOCK_PTR) = n;
g = new_graph (n + 1);
for (y = 0; y < g->n_vertices; y++)
@ -1357,7 +1357,7 @@ iterate_fix_dominators (enum cdi_direction dir, vec<basic_block> bbs,
if (dom == bb)
continue;
dom_i = (size_t) *pointer_map_contains (map, dom);
dom_i = *map->contains (dom);
/* Do not include parallel edges to G. */
if (!bitmap_set_bit ((bitmap) g->vertices[dom_i].data, i))
@ -1368,7 +1368,7 @@ iterate_fix_dominators (enum cdi_direction dir, vec<basic_block> bbs,
}
for (y = 0; y < g->n_vertices; y++)
BITMAP_FREE (g->vertices[y].data);
pointer_map_destroy (map);
delete map;
/* Find the dominator tree of G. */
son = XNEWVEC (int, n + 1);

View File

@ -225,20 +225,21 @@ lto_output_decl_index (struct lto_output_stream *obs,
struct lto_tree_ref_encoder *encoder,
tree name, unsigned int *this_index)
{
void **slot;
int index;
unsigned *slot;
unsigned int index;
bool new_entry_p = FALSE;
bool existed_p;
slot = pointer_map_insert (encoder->tree_hash_table, name);
if (*slot == NULL)
slot = encoder->tree_hash_table->insert (name, &existed_p);
if (!existed_p)
{
index = encoder->trees.length ();
*slot = (void *)(uintptr_t) index;
*slot = index;
encoder->trees.safe_push (name);
new_entry_p = TRUE;
}
else
index = (uintptr_t) *slot;
index = *slot;
if (obs)
streamer_write_uhwi_stream (obs, index);
@ -438,7 +439,7 @@ lto_record_function_out_decl_state (tree fn_decl,
for (i = 0; i < LTO_N_DECL_STREAMS; i++)
if (state->streams[i].tree_hash_table)
{
pointer_map_destroy (state->streams[i].tree_hash_table);
delete state->streams[i].tree_hash_table;
state->streams[i].tree_hash_table = NULL;
}
state->fn_decl = fn_decl;

View File

@ -479,7 +479,7 @@ struct GTY(()) lto_tree_ref_table
struct lto_tree_ref_encoder
{
pointer_map_t *tree_hash_table; /* Maps pointers to indices. */
pointer_map<unsigned> *tree_hash_table; /* Maps pointers to indices. */
vec<tree> trees; /* Maps indices to pointers. */
};
@ -997,7 +997,7 @@ lto_tag_check_range (enum LTO_tags actual, enum LTO_tags tag1,
static inline void
lto_init_tree_ref_encoder (struct lto_tree_ref_encoder *encoder)
{
encoder->tree_hash_table = pointer_map_create ();
encoder->tree_hash_table = new pointer_map<unsigned>;
encoder->trees.create (0);
}
@ -1009,7 +1009,7 @@ lto_destroy_tree_ref_encoder (struct lto_tree_ref_encoder *encoder)
{
/* Hash table may be delete already. */
if (encoder->tree_hash_table)
pointer_map_destroy (encoder->tree_hash_table);
delete encoder->tree_hash_table;
encoder->trees.release ();
}

View File

@ -21,21 +21,6 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "pointer-set.h"
/* 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 (yet). There is no mechanism for user control of hash
function, equality comparison, initial size, or resizing policy. */
struct pointer_set_t
{
size_t log_slots;
size_t n_slots; /* n_slots = 2^log_slots */
size_t n_elements;
const void **slots;
};
/* Use the multiplicative method, as described in Knuth 6.4, to obtain
a hash code for P in the range [0, MAX). MAX == 2^LOGMAX.
@ -67,6 +52,7 @@ hash1 (const void *p, unsigned long max, unsigned long logmax)
return ((A * (uintptr_t) p) >> shift) & (max - 1);
}
/* Allocate an empty pointer set. */
struct pointer_set_t *
pointer_set_create (void)
@ -89,20 +75,28 @@ pointer_set_destroy (struct pointer_set_t *pset)
XDELETE (pset);
}
/* Returns nonzero if PSET contains P. P must be nonnull.
Collisions are resolved by linear probing. */
int
pointer_set_contains (const struct pointer_set_t *pset, const void *p)
/* Lookup the slot for the pointer P and return true if it exists,
otherwise return false in which case *IX points to the slot that
would be used on insertion. */
bool
pointer_set_lookup (const pointer_set_t *pset, const void *p, size_t *ix)
{
size_t n = hash1 (p, pset->n_slots, pset->log_slots);
while (true)
{
if (pset->slots[n] == p)
return 1;
{
*ix = n;
return true;
}
else if (pset->slots[n] == 0)
return 0;
{
*ix = n;
return false;
}
else
{
++n;
@ -112,23 +106,14 @@ pointer_set_contains (const struct pointer_set_t *pset, const void *p)
}
}
/* 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 (const void *p, const void **slots, size_t n_slots, size_t log_slots)
/* Returns nonzero if PSET contains P. P must be nonnull.
Collisions are resolved by linear probing. */
int
pointer_set_contains (const struct pointer_set_t *pset, const void *p)
{
size_t n = hash1 (p, n_slots, log_slots);
while (true)
{
if (slots[n] == p || slots[n] == 0)
return n;
else
{
++n;
if (n == n_slots)
n = 0;
}
}
size_t n;
return pointer_set_lookup (pset, p, &n);
}
/* Inserts P into PSET if it wasn't already there. Returns nonzero
@ -142,26 +127,24 @@ pointer_set_insert (struct pointer_set_t *pset, const void *p)
superfluous but can happen at most once. */
if (pset->n_elements > pset->n_slots / 4)
{
size_t new_log_slots = pset->log_slots + 1;
size_t new_n_slots = pset->n_slots * 2;
const void **new_slots = XCNEWVEC (const void *, new_n_slots);
size_t old_n_slots = pset->n_slots;
const void **old_slots = pset->slots;
pset->log_slots = pset->log_slots + 1;
pset->n_slots = pset->n_slots * 2;
pset->slots = XCNEWVEC (const void *, pset->n_slots);
size_t i;
for (i = 0; i < pset->n_slots; ++i)
for (i = 0; i < old_n_slots; ++i)
{
const void *value = pset->slots[i];
n = insert_aux (value, new_slots, new_n_slots, new_log_slots);
new_slots[n] = value;
const void *value = old_slots[i];
pointer_set_lookup (pset, value, &n);
pset->slots[n] = value;
}
XDELETEVEC (pset->slots);
pset->n_slots = new_n_slots;
pset->log_slots = new_log_slots;
pset->slots = new_slots;
XDELETEVEC (old_slots);
}
n = insert_aux (p, pset->slots, pset->n_slots, pset->log_slots);
if (pset->slots[n])
if (pointer_set_lookup (pset, p, &n))
return 1;
pset->slots[n] = p;
@ -190,11 +173,7 @@ void pointer_set_traverse (const struct pointer_set_t *pset,
struct pointer_map_t
{
size_t log_slots;
size_t n_slots; /* n_slots = 2^log_slots */
size_t n_elements;
const void **keys;
pointer_set_t pset;
void **values;
};
@ -204,19 +183,19 @@ 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->pset.n_elements = 0;
result->pset.log_slots = 8;
result->pset.n_slots = (size_t) 1 << result->pset.log_slots;
result->keys = XCNEWVEC (const void *, result->n_slots);
result->values = XCNEWVEC (void *, result->n_slots);
result->pset.slots = XCNEWVEC (const void *, result->pset.n_slots);
result->values = XCNEWVEC (void *, result->pset.n_slots);
return result;
}
/* Reclaims all memory associated with PMAP. */
void pointer_map_destroy (struct pointer_map_t *pmap)
{
XDELETEVEC (pmap->keys);
XDELETEVEC (pmap->pset.slots);
XDELETEVEC (pmap->values);
XDELETE (pmap);
}
@ -228,21 +207,11 @@ void pointer_map_destroy (struct pointer_map_t *pmap)
void **
pointer_map_contains (const struct pointer_map_t *pmap, const 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;
}
}
size_t n;
if (pointer_set_lookup (&pmap->pset, p, &n))
return &pmap->values[n];
else
return NULL;
}
/* Inserts P into PMAP if it wasn't already there. Returns a pointer
@ -254,36 +223,34 @@ pointer_map_insert (struct pointer_map_t *pmap, const void *p)
/* 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)
if (pmap->pset.n_elements > pmap->pset.n_slots / 4)
{
size_t new_log_slots = pmap->log_slots + 1;
size_t new_n_slots = pmap->n_slots * 2;
const void **new_keys = XCNEWVEC (const void *, new_n_slots);
void **new_values = XCNEWVEC (void *, new_n_slots);
size_t old_n_slots = pmap->pset.n_slots;
const void **old_keys = pmap->pset.slots;
void **old_values = pmap->values;
pmap->pset.log_slots = pmap->pset.log_slots + 1;
pmap->pset.n_slots = pmap->pset.n_slots * 2;
pmap->pset.slots = XCNEWVEC (const void *, pmap->pset.n_slots);
pmap->values = XCNEWVEC (void *, pmap->pset.n_slots);
size_t i;
for (i = 0; i < pmap->n_slots; ++i)
if (pmap->keys[i])
for (i = 0; i < old_n_slots; ++i)
if (old_keys[i])
{
const 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];
const void *key = old_keys[i];
pointer_set_lookup (&pmap->pset, key, &n);
pmap->pset.slots[n] = key;
pmap->values[n] = old_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;
XDELETEVEC (old_keys);
XDELETEVEC (old_values);
}
n = insert_aux (p, pmap->keys, pmap->n_slots, pmap->log_slots);
if (!pmap->keys[n])
if (!pointer_set_lookup (&pmap->pset, p, &n))
{
++pmap->n_elements;
pmap->keys[n] = p;
++pmap->pset.n_elements;
pmap->pset.slots[n] = p;
}
return &pmap->values[n];
@ -297,7 +264,8 @@ void pointer_map_traverse (const struct pointer_map_t *pmap,
bool (*fn) (const 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))
for (i = 0; i < pmap->pset.n_slots; ++i)
if (pmap->pset.slots[i]
&& !fn (pmap->pset.slots[i], &pmap->values[i], data))
break;
}

View File

@ -20,23 +20,151 @@ along with GCC; see the file COPYING3. If not see
#ifndef POINTER_SET_H
#define POINTER_SET_H
struct pointer_set_t;
/* 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 (yet). There is no mechanism for user control of hash
function, equality comparison, initial size, or resizing policy. */
struct pointer_set_t
{
size_t log_slots;
size_t n_slots; /* n_slots = 2^log_slots */
size_t n_elements;
const void **slots;
};
struct pointer_set_t *pointer_set_create (void);
void pointer_set_destroy (struct pointer_set_t *pset);
int pointer_set_contains (const struct pointer_set_t *pset, const void *p);
int pointer_set_insert (struct pointer_set_t *pset, const void *p);
void pointer_set_traverse (const struct pointer_set_t *,
bool (*) (const void *, void *),
void *);
bool pointer_set_lookup (const pointer_set_t *, const void *, size_t *);
/* 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. */
template <typename T>
class pointer_map : protected pointer_set_t
{
T *values;
public:
pointer_map ();
~pointer_map ();
T *contains (const void *p);
T *insert (const void *p, bool *existed_p = NULL);
void traverse (bool (*fn) (const void *, T *, void *), void *data);
};
/* Allocate an empty pointer map. */
template <typename T>
pointer_map<T>::pointer_map (void)
{
n_elements = 0;
log_slots = 8;
n_slots = (size_t) 1 << log_slots;
slots = XCNEWVEC (const void *, n_slots);
values = XNEWVEC (T, n_slots);
}
/* Reclaims all memory associated with PMAP. */
template <typename T>
pointer_map<T>::~pointer_map (void)
{
XDELETEVEC (slots);
XDELETEVEC (values);
}
/* 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. */
template <typename T>
T *
pointer_map<T>::contains (const void *p)
{
size_t n;
if (!pointer_set_lookup (this, p, &n))
return NULL;
return &values[n];
}
/* Inserts P into PMAP if it wasn't already there. Returns a pointer
to the value. P must be nonnull. */
template <typename T>
T *
pointer_map<T>::insert (const void *p, bool *existed_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. */
/* ??? Fugly that we have to inline that here. */
if (n_elements > n_slots / 4)
{
size_t old_n_slots = n_slots;
const void **old_keys = slots;
T *old_values = values;
log_slots = log_slots + 1;
n_slots = n_slots * 2;
slots = XCNEWVEC (const void *, n_slots);
values = XNEWVEC (T, n_slots);
for (size_t i = 0; i < old_n_slots; ++i)
if (old_keys[i])
{
const void *key = old_keys[i];
pointer_set_lookup (this, key, &n);
slots[n] = key;
values[n] = old_values[i];
}
XDELETEVEC (old_keys);
XDELETEVEC (old_values);
}
if (!pointer_set_lookup (this, p, &n))
{
++n_elements;
slots[n] = p;
if (existed_p)
*existed_p = false;
}
else if (existed_p)
*existed_p = true;
return &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. */
template <class T>
void
pointer_map<T>::traverse (bool (*fn) (const void *, T *, void *), void *data)
{
for (size_t i = 0; i < n_slots; ++i)
if (slots[i] && !fn (slots[i], &values[i], data))
break;
}
struct pointer_map_t;
struct pointer_map_t *pointer_map_create (void);
void pointer_map_destroy (struct pointer_map_t *pmap);
pointer_map_t *pointer_map_create (void);
void pointer_map_destroy (pointer_map_t *pmap);
void **pointer_map_contains (const struct pointer_map_t *pmap, const void *p);
void **pointer_map_insert (struct pointer_map_t *pmap, const void *p);
void pointer_map_traverse (const struct pointer_map_t *,
void **pointer_map_contains (const pointer_map_t *pmap, const void *p);
void **pointer_map_insert (pointer_map_t *pmap, const void *p);
void pointer_map_traverse (const pointer_map_t *,
bool (*) (const void *, void **, void *), void *);
#endif /* POINTER_SET_H */

View File

@ -128,30 +128,27 @@ streamer_tree_cache_insert_1 (struct streamer_tree_cache_d *cache,
tree t, hashval_t hash, unsigned *ix_p,
bool insert_at_next_slot_p)
{
void **slot;
unsigned *slot;
unsigned ix;
bool existed_p;
gcc_assert (t);
slot = pointer_map_insert (cache->node_map, t);
if (!*slot)
slot = cache->node_map->insert (t, &existed_p);
if (!existed_p)
{
/* Determine the next slot to use in the cache. */
if (insert_at_next_slot_p)
ix = cache->nodes.length ();
else
ix = *ix_p;
*slot = (void *)(size_t) (ix + 1);
*slot = ix;
streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
/* Indicate that the item was not present in the cache. */
existed_p = false;
}
else
{
ix = (size_t) *slot - 1;
ix = *slot;
if (!insert_at_next_slot_p && ix != *ix_p)
{
@ -160,11 +157,8 @@ streamer_tree_cache_insert_1 (struct streamer_tree_cache_d *cache,
the requested location slot. */
ix = *ix_p;
streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
*slot = (void *)(size_t) (ix + 1);
*slot = ix;
}
/* Indicate that T was already in the cache. */
existed_p = true;
}
if (ix_p)
@ -225,13 +219,13 @@ bool
streamer_tree_cache_lookup (struct streamer_tree_cache_d *cache, tree t,
unsigned *ix_p)
{
void **slot;
unsigned *slot;
bool retval;
unsigned ix;
gcc_assert (t);
slot = pointer_map_contains (cache->node_map, t);
slot = cache->node_map->contains (t);
if (slot == NULL)
{
retval = false;
@ -240,7 +234,7 @@ streamer_tree_cache_lookup (struct streamer_tree_cache_d *cache, tree t,
else
{
retval = true;
ix = (size_t) *slot - 1;
ix = *slot;
}
if (ix_p)
@ -332,7 +326,7 @@ streamer_tree_cache_create (bool with_hashes, bool with_map)
cache = XCNEW (struct streamer_tree_cache_d);
if (with_map)
cache->node_map = pointer_map_create ();
cache->node_map = new pointer_map<unsigned>;
cache->nodes.create (165);
if (with_hashes)
cache->hashes.create (165);
@ -355,7 +349,7 @@ streamer_tree_cache_delete (struct streamer_tree_cache_d *c)
return;
if (c->node_map)
pointer_map_destroy (c->node_map);
delete c->node_map;
c->nodes.release ();
c->hashes.release ();
free (c);

View File

@ -47,7 +47,7 @@ along with GCC; see the file COPYING3. If not see
struct streamer_tree_cache_d
{
/* The mapping between tree nodes and slots into the nodes array. */
struct pointer_map_t *node_map;
pointer_map<unsigned> *node_map;
/* The nodes pickled so far. */
vec<tree> nodes;