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:
parent
e04518ae25
commit
7c5848b899
8 changed files with 266 additions and 140 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue