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:
parent
f7b410e0fb
commit
9fa2efcd3d
@ -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>
|
||||
|
||||
PR middle-end/30028
|
||||
|
@ -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. */
|
||||
|
||||
coalesce_list_p
|
||||
create_coalesce_list (var_map map)
|
||||
{
|
||||
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->sorted = NULL;
|
||||
list->add_mode = true;
|
||||
list->list = (partition_pair_p *) xcalloc (num_var_partitions (map),
|
||||
sizeof (struct partition_pair_d));
|
||||
list->num_sorted = 0;
|
||||
return list;
|
||||
}
|
||||
|
||||
@ -1158,7 +1193,10 @@ create_coalesce_list (var_map map)
|
||||
void
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1170,52 +1208,38 @@ delete_coalesce_list (coalesce_list_p cl)
|
||||
static partition_pair_p
|
||||
find_partition_pair (coalesce_list_p cl, int p1, int p2, bool create)
|
||||
{
|
||||
partition_pair_p node, tmp;
|
||||
int s;
|
||||
struct partition_pair p, *pair;
|
||||
void **slot;
|
||||
unsigned int hash;
|
||||
|
||||
/* Normalize so that p1 is the smaller value. */
|
||||
/* normalize so that p1 is the smaller value. */
|
||||
if (p2 < p1)
|
||||
{
|
||||
s = p1;
|
||||
p1 = p2;
|
||||
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;
|
||||
p.first_partition = p2;
|
||||
p.second_partition = p1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is now the first node in the list. */
|
||||
node->next = cl->list[p1];
|
||||
cl->list[p1] = node;
|
||||
p.first_partition = p1;
|
||||
p.second_partition = p2;
|
||||
}
|
||||
|
||||
|
||||
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 node;
|
||||
return pair;
|
||||
}
|
||||
|
||||
/* 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
|
||||
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
|
||||
0 has all the coalesce pairs, sorted in order from most important coalesce
|
||||
to least important. */
|
||||
@ -1272,64 +1337,45 @@ int compare_pairs (const void *p1, const void *p2)
|
||||
void
|
||||
sort_coalesce_list (coalesce_list_p cl)
|
||||
{
|
||||
unsigned x, num, count;
|
||||
partition_pair_p chain, p;
|
||||
partition_pair_p *list;
|
||||
unsigned x, num;
|
||||
partition_pair_p p;
|
||||
partition_pair_iterator ppi;
|
||||
|
||||
gcc_assert (cl->add_mode);
|
||||
|
||||
cl->add_mode = false;
|
||||
|
||||
/* Compact the array of lists to a single list, and count the elements. */
|
||||
num = 0;
|
||||
chain = NULL;
|
||||
for (x = 0; x < num_var_partitions (cl->map); x++)
|
||||
if (cl->list[x] != NULL)
|
||||
{
|
||||
for (p = cl->list[x]; p->next != NULL; p = p->next)
|
||||
num++;
|
||||
num++;
|
||||
p->next = chain;
|
||||
chain = cl->list[x];
|
||||
cl->list[x] = NULL;
|
||||
}
|
||||
/* allocate a vector for the pair pointers. */
|
||||
num = num_coalesce_pairs (cl);
|
||||
cl->num_sorted = num;
|
||||
if (num == 0)
|
||||
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)
|
||||
{
|
||||
if (cl->sorted[0]->cost > cl->sorted[1]->cost)
|
||||
{
|
||||
p = cl->sorted[0];
|
||||
cl->sorted[0] = cl->sorted[1];
|
||||
cl->sorted[1] = p;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only call qsort if there are more than 2 items. */
|
||||
if (num > 2)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
qsort (cl->sorted, num, sizeof (partition_pair_p), compare_pairs);
|
||||
}
|
||||
|
||||
|
||||
@ -1345,11 +1391,10 @@ pop_best_coalesce (coalesce_list_p cl, int *p1, int *p2)
|
||||
|
||||
gcc_assert (!cl->add_mode);
|
||||
|
||||
node = cl->list[0];
|
||||
if (!node)
|
||||
if (cl->num_sorted == 0)
|
||||
return NO_BEST_COALESCE;
|
||||
|
||||
cl->list[0] = node->next;
|
||||
node = cl->sorted[--(cl->num_sorted)];
|
||||
|
||||
*p1 = node->first_partition;
|
||||
*p2 = node->second_partition;
|
||||
@ -1729,40 +1774,34 @@ void
|
||||
dump_coalesce_list (FILE *f, coalesce_list_p cl)
|
||||
{
|
||||
partition_pair_p node;
|
||||
int x, num;
|
||||
partition_pair_iterator ppi;
|
||||
int x;
|
||||
tree var;
|
||||
|
||||
if (cl->add_mode)
|
||||
{
|
||||
fprintf (f, "Coalesce List:\n");
|
||||
num = num_var_partitions (cl->map);
|
||||
for (x = 0; x < num; x++)
|
||||
FOR_EACH_PARTITION_PAIR (node, ppi, cl)
|
||||
{
|
||||
node = cl->list[x];
|
||||
if (node)
|
||||
{
|
||||
fprintf (f, "[");
|
||||
print_generic_expr (f, partition_to_var (cl->map, x), TDF_SLIM);
|
||||
fprintf (f, "] - ");
|
||||
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");
|
||||
}
|
||||
tree var1 = partition_to_var (cl->map, node->first_partition);
|
||||
tree var2 = partition_to_var (cl->map, node->second_partition);
|
||||
print_generic_expr (f, var1, TDF_SLIM);
|
||||
fprintf (f, " <-> ");
|
||||
print_generic_expr (f, var2, TDF_SLIM);
|
||||
fprintf (f, " (%1d), ", node->cost);
|
||||
fprintf (f, "\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
var = partition_to_var (cl->map, node->first_partition);
|
||||
print_generic_expr (f, var, TDF_SLIM);
|
||||
fprintf (f, " : ");
|
||||
fprintf (f, " <-> ");
|
||||
var = partition_to_var (cl->map, node->second_partition);
|
||||
print_generic_expr (f, var, TDF_SLIM);
|
||||
fprintf (f, "\n");
|
||||
|
@ -147,7 +147,7 @@ var_to_partition (var_map map, tree var)
|
||||
else
|
||||
{
|
||||
ann = var_ann (var);
|
||||
if (ann->out_of_ssa_tag)
|
||||
if (ann && ann->out_of_ssa_tag)
|
||||
part = VAR_ANN_PARTITION (ann);
|
||||
else
|
||||
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
|
||||
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 second_partition;
|
||||
int cost;
|
||||
struct partition_pair_d *next;
|
||||
} *partition_pair_p;
|
||||
} * partition_pair_p;
|
||||
|
||||
/* This structure maintains the list of coalesce pairs.
|
||||
When add_mode is true, list is a triangular shaped list of coalesce pairs.
|
||||
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
|
||||
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. */
|
||||
extern unsigned int partition_pair_map_hash (const void *);
|
||||
extern int partition_pair_map_eq (const void *, const void *);
|
||||
|
||||
/* This structure maintains the list of coalesce pairs. */
|
||||
|
||||
typedef struct coalesce_list_d
|
||||
{
|
||||
var_map map;
|
||||
partition_pair_p *list;
|
||||
htab_t list;
|
||||
partition_pair_p *sorted;
|
||||
int num_sorted;
|
||||
bool add_mode;
|
||||
} *coalesce_list_p;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user