From 9fa2efcd3d3adb1eac151d510ef2c8dd1799b4a0 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Thu, 30 Nov 2006 21:36:32 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 22 ++++ gcc/tree-ssa-live.c | 271 +++++++++++++++++++++++++------------------- gcc/tree-ssa-live.h | 27 ++--- 3 files changed, 188 insertions(+), 132 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 44bb553c6e5..e9d4055d114 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2006-11-30 Andrew Macleod + + * 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 PR middle-end/30028 diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c index b34190f219f..e1525c1d003 100644 --- a/gcc/tree-ssa-live.c +++ b/gcc/tree-ssa-live.c @@ -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"); diff --git a/gcc/tree-ssa-live.h b/gcc/tree-ssa-live.h index f0c59028e19..17ada27bda7 100644 --- a/gcc/tree-ssa-live.h +++ b/gcc/tree-ssa-live.h @@ -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;