Implement coalesce list with hash table instead of linked list.

* tree-ssa-live.c (create_coalesce_list): Create a hash table.
	(COALESCE_HASH_FN): New.  Define hash function.
	(partition_pair_map_hash): New.  Hash value for a partition pair.
	(partition_pair_map_eq): New.  Equality for hash pairs.
	(create_coalesce_list): Create hash table.
	(delete_coalesce_list): Free hash table.
	(find_partition_pair): Find/create pairs in hash table.
	(compare_pairs):  Sort pairs in ascending order now.
	(num_coalesce_pairs): New.  Number of pairs in hash table.
	(struct partition_pair_iterator): Iterator struct for pair table.
	(first_partition_pair): Iterator function for first pair.
	(end_partition_pair_p): Iterator function for end of iteration.
	(next_partition_pair): Iterator function for next pair.
	(FOR_EACH_PARTITION_PAIR): Macro for iterating over pairs.
	(sort_coalesce_list): Sort pairs from hash table into an array.
	(pop_best_coalesce): Take pairs from the array.
	(dump_coalesce_list): Update to use hash table or sorted array.
	* tree-ssa-live.h (struct partition_pair_d): Remove next field.
	(struct coalesce_list_d): Add hash table related fields.

From-SVN: r119378
This commit is contained in:
Andrew MacLeod 2006-11-30 21:36:32 +00:00 committed by Andrew Macleod
parent f7b410e0fb
commit 9fa2efcd3d
3 changed files with 188 additions and 132 deletions

View File

@ -1,3 +1,25 @@
2006-11-30 Andrew Macleod <amacleod@redhat.com>
* tree-ssa-live.c (create_coalesce_list): Create a hash table.
(COALESCE_HASH_FN): New. Define hash function.
(partition_pair_map_hash): New. Hash value for a partition pair.
(partition_pair_map_eq): New. Equality for hash pairs.
(create_coalesce_list): Create hash table.
(delete_coalesce_list): Free hash table.
(find_partition_pair): Find/create pairs in hash table.
(compare_pairs): Sort pairs in ascending order now.
(num_coalesce_pairs): New. Number of pairs in hash table.
(struct partition_pair_iterator): Iterator struct for pair table.
(first_partition_pair): Iterator function for first pair.
(end_partition_pair_p): Iterator function for end of iteration.
(next_partition_pair): Iterator function for next pair.
(FOR_EACH_PARTITION_PAIR): Macro for iterating over pairs.
(sort_coalesce_list): Sort pairs from hash table into an array.
(pop_best_coalesce): Take pairs from the array.
(dump_coalesce_list): Update to use hash table or sorted array.
* tree-ssa-live.h (struct partition_pair_d): Remove next field.
(struct coalesce_list_d): Add hash table related fields.
2006-11-30 Jan Hubicka <jh@suse.cz> 2006-11-30 Jan Hubicka <jh@suse.cz>
PR middle-end/30028 PR middle-end/30028

View File

@ -1136,19 +1136,54 @@ type_var_init (var_map map)
} }
/* Hash function for 2 integer coalesce pairs. */
#define COALESCE_HASH_FN(R1, R2) ((R2) * ((R2) - 1) / 2 + (R1))
/* Return hash value for partition pair PAIR. */
unsigned int
partition_pair_map_hash (const void *pair)
{
hashval_t a = (hashval_t)(((partition_pair_p)pair)->first_partition);
hashval_t b = (hashval_t)(((partition_pair_p)pair)->second_partition);
return COALESCE_HASH_FN (a,b);
}
/* Return TRUE if PAIR1 is equivilent to PAIR2. */
int
partition_pair_map_eq (const void *pair1, const void *pair2)
{
partition_pair_p p1 = (partition_pair_p) pair1;
partition_pair_p p2 = (partition_pair_p) pair2;
return (p1->first_partition == p2->first_partition
&& p1->second_partition == p2->second_partition);
}
/* Create a new coalesce list object from MAP and return it. */ /* Create a new coalesce list object from MAP and return it. */
coalesce_list_p coalesce_list_p
create_coalesce_list (var_map map) create_coalesce_list (var_map map)
{ {
coalesce_list_p list; coalesce_list_p list;
unsigned size = num_ssa_names * 3;
list = (coalesce_list_p) xmalloc (sizeof (struct coalesce_list_d)); if (size < 40)
size = 40;
list = xmalloc (sizeof (struct coalesce_list_d));
list->list = htab_create (size, partition_pair_map_hash,
partition_pair_map_eq, NULL);
list->map = map; list->map = map;
list->sorted = NULL;
list->add_mode = true; list->add_mode = true;
list->list = (partition_pair_p *) xcalloc (num_var_partitions (map), list->num_sorted = 0;
sizeof (struct partition_pair_d));
return list; return list;
} }
@ -1158,7 +1193,10 @@ create_coalesce_list (var_map map)
void void
delete_coalesce_list (coalesce_list_p cl) delete_coalesce_list (coalesce_list_p cl)
{ {
free (cl->list); htab_delete (cl->list);
if (cl->sorted)
free (cl->sorted);
gcc_assert (cl->num_sorted == 0);
free (cl); free (cl);
} }
@ -1170,52 +1208,38 @@ delete_coalesce_list (coalesce_list_p cl)
static partition_pair_p static partition_pair_p
find_partition_pair (coalesce_list_p cl, int p1, int p2, bool create) find_partition_pair (coalesce_list_p cl, int p1, int p2, bool create)
{ {
partition_pair_p node, tmp; struct partition_pair p, *pair;
int s; void **slot;
unsigned int hash;
/* Normalize so that p1 is the smaller value. */ /* normalize so that p1 is the smaller value. */
if (p2 < p1) if (p2 < p1)
{ {
s = p1; p.first_partition = p2;
p1 = p2; p.second_partition = p1;
p2 = s;
}
tmp = NULL;
/* The list is sorted such that if we find a value greater than p2,
p2 is not in the list. */
for (node = cl->list[p1]; node; node = node->next)
{
if (node->second_partition == p2)
return node;
else
if (node->second_partition > p2)
break;
tmp = node;
}
if (!create)
return NULL;
node = (partition_pair_p) xmalloc (sizeof (struct partition_pair_d));
node->first_partition = p1;
node->second_partition = p2;
node->cost = 0;
if (tmp != NULL)
{
node->next = tmp->next;
tmp->next = node;
} }
else else
{ {
/* This is now the first node in the list. */ p.first_partition = p1;
node->next = cl->list[p1]; p.second_partition = p2;
cl->list[p1] = node;
} }
return node;
hash = partition_pair_map_hash (&p);
pair = (struct partition_pair *) htab_find_with_hash (cl->list, &p, hash);
if (create && !pair)
{
gcc_assert (cl->add_mode);
pair = xmalloc (sizeof (struct partition_pair));
pair->first_partition = p.first_partition;
pair->second_partition = p.second_partition;
pair->cost = 0;
slot = htab_find_slot_with_hash (cl->list, pair, hash, INSERT);
*(struct partition_pair **)slot = pair;
}
return pair;
} }
/* Return cost of execution of copy instruction with FREQUENCY /* Return cost of execution of copy instruction with FREQUENCY
@ -1256,15 +1280,56 @@ add_coalesce (coalesce_list_p cl, int p1, int p2,
} }
/* Comparison function to allow qsort to sort P1 and P2 in descending order. */ /* Comparison function to allow qsort to sort P1 and P2 in Ascendiong order. */
static static
int compare_pairs (const void *p1, const void *p2) int compare_pairs (const void *p1, const void *p2)
{ {
return (*(partition_pair_p *)p2)->cost - (*(partition_pair_p *)p1)->cost; return (*(partition_pair_p *)p1)->cost - (*(partition_pair_p *)p2)->cost;
} }
static inline int
num_coalesce_pairs (coalesce_list_p cl)
{
return htab_elements (cl->list);
}
typedef struct
{
htab_iterator hti;
} partition_pair_iterator;
static inline partition_pair_p
first_partition_pair (coalesce_list_p cl, partition_pair_iterator *iter)
{
partition_pair_p pair;
pair = (partition_pair_p) first_htab_element (&(iter->hti), cl->list);
return pair;
}
static inline bool
end_partition_pair_p (partition_pair_iterator *iter)
{
return end_htab_p (&(iter->hti));
}
static inline partition_pair_p
next_partition_pair (partition_pair_iterator *iter)
{
partition_pair_p pair;
pair = (partition_pair_p) next_htab_element (&(iter->hti));
return pair;
}
#define FOR_EACH_PARTITION_PAIR(PAIR, ITER, CL) \
for ((PAIR) = first_partition_pair ((CL), &(ITER)); \
!end_partition_pair_p (&(ITER)); \
(PAIR) = next_partition_pair (&(ITER)))
/* Prepare CL for removal of preferred pairs. When finished, list element /* Prepare CL for removal of preferred pairs. When finished, list element
0 has all the coalesce pairs, sorted in order from most important coalesce 0 has all the coalesce pairs, sorted in order from most important coalesce
to least important. */ to least important. */
@ -1272,64 +1337,45 @@ int compare_pairs (const void *p1, const void *p2)
void void
sort_coalesce_list (coalesce_list_p cl) sort_coalesce_list (coalesce_list_p cl)
{ {
unsigned x, num, count; unsigned x, num;
partition_pair_p chain, p; partition_pair_p p;
partition_pair_p *list; partition_pair_iterator ppi;
gcc_assert (cl->add_mode); gcc_assert (cl->add_mode);
cl->add_mode = false; cl->add_mode = false;
/* Compact the array of lists to a single list, and count the elements. */ /* allocate a vector for the pair pointers. */
num = 0; num = num_coalesce_pairs (cl);
chain = NULL; cl->num_sorted = num;
for (x = 0; x < num_var_partitions (cl->map); x++) if (num == 0)
if (cl->list[x] != NULL) return;
cl->sorted = XNEWVEC (partition_pair_p, num);
/* Populate the vector with pointers to the partition pairs. */
x = 0;
FOR_EACH_PARTITION_PAIR (p, ppi, cl)
cl->sorted[x++] = p;
gcc_assert (x == num);
if (num == 1)
return;
if (num == 2)
{ {
for (p = cl->list[x]; p->next != NULL; p = p->next) if (cl->sorted[0]->cost > cl->sorted[1]->cost)
num++; {
num++; p = cl->sorted[0];
p->next = chain; cl->sorted[0] = cl->sorted[1];
chain = cl->list[x]; cl->sorted[1] = p;
cl->list[x] = NULL; }
return;
} }
/* Only call qsort if there are more than 2 items. */ /* Only call qsort if there are more than 2 items. */
if (num > 2) if (num > 2)
{ qsort (cl->sorted, num, sizeof (partition_pair_p), compare_pairs);
list = XNEWVEC (partition_pair_p, num);
count = 0;
for (p = chain; p != NULL; p = p->next)
list[count++] = p;
gcc_assert (count == num);
qsort (list, count, sizeof (partition_pair_p), compare_pairs);
p = list[0];
for (x = 1; x < num; x++)
{
p->next = list[x];
p = list[x];
}
p->next = NULL;
cl->list[0] = list[0];
free (list);
}
else
{
cl->list[0] = chain;
if (num == 2)
{
/* Simply swap the two elements if they are in the wrong order. */
if (chain->cost < chain->next->cost)
{
cl->list[0] = chain->next;
cl->list[0]->next = chain;
chain->next = NULL;
}
}
}
} }
@ -1345,11 +1391,10 @@ pop_best_coalesce (coalesce_list_p cl, int *p1, int *p2)
gcc_assert (!cl->add_mode); gcc_assert (!cl->add_mode);
node = cl->list[0]; if (cl->num_sorted == 0)
if (!node)
return NO_BEST_COALESCE; return NO_BEST_COALESCE;
cl->list[0] = node->next; node = cl->sorted[--(cl->num_sorted)];
*p1 = node->first_partition; *p1 = node->first_partition;
*p2 = node->second_partition; *p2 = node->second_partition;
@ -1729,40 +1774,34 @@ void
dump_coalesce_list (FILE *f, coalesce_list_p cl) dump_coalesce_list (FILE *f, coalesce_list_p cl)
{ {
partition_pair_p node; partition_pair_p node;
int x, num; partition_pair_iterator ppi;
int x;
tree var; tree var;
if (cl->add_mode) if (cl->add_mode)
{ {
fprintf (f, "Coalesce List:\n"); fprintf (f, "Coalesce List:\n");
num = num_var_partitions (cl->map); FOR_EACH_PARTITION_PAIR (node, ppi, cl)
for (x = 0; x < num; x++)
{ {
node = cl->list[x]; tree var1 = partition_to_var (cl->map, node->first_partition);
if (node) tree var2 = partition_to_var (cl->map, node->second_partition);
{ print_generic_expr (f, var1, TDF_SLIM);
fprintf (f, "["); fprintf (f, " <-> ");
print_generic_expr (f, partition_to_var (cl->map, x), TDF_SLIM); print_generic_expr (f, var2, TDF_SLIM);
fprintf (f, "] - "); fprintf (f, " (%1d), ", node->cost);
for ( ; node; node = node->next)
{
var = partition_to_var (cl->map, node->second_partition);
print_generic_expr (f, var, TDF_SLIM);
fprintf (f, "(%1d), ", node->cost);
}
fprintf (f, "\n"); fprintf (f, "\n");
} }
} }
}
else else
{ {
fprintf (f, "Sorted Coalesce list:\n"); fprintf (f, "Sorted Coalesce list:\n");
for (node = cl->list[0]; node; node = node->next) for (x = cl->num_sorted - 1 ; x >=0; x--)
{ {
node = cl->sorted[x];
fprintf (f, "(%d) ", node->cost); fprintf (f, "(%d) ", node->cost);
var = partition_to_var (cl->map, node->first_partition); var = partition_to_var (cl->map, node->first_partition);
print_generic_expr (f, var, TDF_SLIM); print_generic_expr (f, var, TDF_SLIM);
fprintf (f, " : "); fprintf (f, " <-> ");
var = partition_to_var (cl->map, node->second_partition); var = partition_to_var (cl->map, node->second_partition);
print_generic_expr (f, var, TDF_SLIM); print_generic_expr (f, var, TDF_SLIM);
fprintf (f, "\n"); fprintf (f, "\n");

View File

@ -147,7 +147,7 @@ var_to_partition (var_map map, tree var)
else else
{ {
ann = var_ann (var); ann = var_ann (var);
if (ann->out_of_ssa_tag) if (ann && ann->out_of_ssa_tag)
part = VAR_ANN_PARTITION (ann); part = VAR_ANN_PARTITION (ann);
else else
part = NO_PARTITION; part = NO_PARTITION;
@ -671,31 +671,26 @@ type_var_decompact (type_var_p tv)
all desired information has been collected, the object can be used to all desired information has been collected, the object can be used to
order the pairs for processing. */ order the pairs for processing. */
/* This structure defines a pair for coalescing. */ /* This structure defines a pair entry. */
typedef struct partition_pair_d typedef struct partition_pair
{ {
int first_partition; int first_partition;
int second_partition; int second_partition;
int cost; int cost;
struct partition_pair_d *next; } * partition_pair_p;
} *partition_pair_p;
/* This structure maintains the list of coalesce pairs. extern unsigned int partition_pair_map_hash (const void *);
When add_mode is true, list is a triangular shaped list of coalesce pairs. extern int partition_pair_map_eq (const void *, const void *);
The smaller partition number is used to index the list, and the larger is
index is located in a partition_pair_p object. These lists are sorted from /* This structure maintains the list of coalesce pairs. */
smallest to largest by 'second_partition'. New coalesce pairs are allowed
to be added in this mode.
When add_mode is false, the lists have all been merged into list[0]. The
rest of the lists are not used. list[0] is ordered from most desirable
coalesce to least desirable. pop_best_coalesce() retrieves the pairs
one at a time. */
typedef struct coalesce_list_d typedef struct coalesce_list_d
{ {
var_map map; var_map map;
partition_pair_p *list; htab_t list;
partition_pair_p *sorted;
int num_sorted;
bool add_mode; bool add_mode;
} *coalesce_list_p; } *coalesce_list_p;