- for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
- {
- stmt = bsi_stmt (bsi);
- get_stmt_operands (stmt);
- ann = stmt_ann (stmt);
-
- FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
- {
- add_livein_if_notdef (live, saw_def, op, bb);
- }
-
- FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
- {
- set_if_valid (map, saw_def, op);
- }
- }
- }
-
- VARRAY_INT_INIT (stack, last_basic_block, "stack");
- EXECUTE_IF_SET_IN_BITMAP (live->global, 0, i, bi)
- {
- live_worklist (live, stack, i);
- }
-
-#ifdef ENABLE_CHECKING
- /* Check for live on entry partitions and report those with a DEF in
- the program. This will typically mean an optimization has done
- something wrong. */
-
- bb = ENTRY_BLOCK_PTR;
- num = 0;
- FOR_EACH_EDGE (e, ei, bb->succs)
- {
- int entry_block = e->dest->index;
- if (e->dest == EXIT_BLOCK_PTR)
- continue;
- for (i = 0; i < num_var_partitions (map); i++)
- {
- basic_block tmp;
- tree d;
- var = partition_to_var (map, i);
- stmt = SSA_NAME_DEF_STMT (var);
- tmp = bb_for_stmt (stmt);
- d = default_def (SSA_NAME_VAR (var));
-
- if (bitmap_bit_p (live_entry_blocks (live, i), entry_block))
- {
- if (!IS_EMPTY_STMT (stmt))
- {
- num++;
- print_generic_expr (stderr, var, TDF_SLIM);
- fprintf (stderr, " is defined ");
- if (tmp)
- fprintf (stderr, " in BB%d, ", tmp->index);
- fprintf (stderr, "by:\n");
- print_generic_expr (stderr, stmt, TDF_SLIM);
- fprintf (stderr, "\nIt is also live-on-entry to entry BB %d",
- entry_block);
- fprintf (stderr, " So it appears to have multiple defs.\n");
- }
- else
- {
- if (d != var)
- {
- num++;
- print_generic_expr (stderr, var, TDF_SLIM);
- fprintf (stderr, " is live-on-entry to BB%d ",entry_block);
- if (d)
- {
- fprintf (stderr, " but is not the default def of ");
- print_generic_expr (stderr, d, TDF_SLIM);
- fprintf (stderr, "\n");
- }
- else
- fprintf (stderr, " and there is no default def.\n");
- }
- }
- }
- else
- if (d == var)
- {
- /* The only way this var shouldn't be marked live on entry is
- if it occurs in a PHI argument of the block. */
- int z, ok = 0;
- for (phi = phi_nodes (e->dest);
- phi && !ok;
- phi = PHI_CHAIN (phi))
- {
- for (z = 0; z < PHI_NUM_ARGS (phi); z++)
- if (var == PHI_ARG_DEF (phi, z))
- {
- ok = 1;
- break;
- }
- }
- if (ok)
- continue;
- num++;
- print_generic_expr (stderr, var, TDF_SLIM);
- fprintf (stderr, " is not marked live-on-entry to entry BB%d ",
- entry_block);
- fprintf (stderr, "but it is a default def so it should be.\n");
- }
- }
- }
- gcc_assert (num <= 0);
-#endif
-
- BITMAP_XFREE (saw_def);
-
- return live;
-}
-
-
-/* Calculate the live on exit vectors based on the entry info in LIVEINFO. */
-
-void
-calculate_live_on_exit (tree_live_info_p liveinfo)
-{
- unsigned b;
- int i, x;
- bitmap *on_exit;
- basic_block bb;
- edge e;
- tree t, phi;
- bitmap on_entry;
- var_map map = liveinfo->map;
-
- on_exit = (bitmap *)xmalloc (last_basic_block * sizeof (bitmap));
- for (x = 0; x < last_basic_block; x++)
- on_exit[x] = BITMAP_XMALLOC ();
-
- /* Set all the live-on-exit bits for uses in PHIs. */
- FOR_EACH_BB (bb)
- {
- for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
- for (i = 0; i < PHI_NUM_ARGS (phi); i++)
- {
- t = PHI_ARG_DEF (phi, i);
- e = PHI_ARG_EDGE (phi, i);
- if (!phi_ssa_name_p (t) || e->src == ENTRY_BLOCK_PTR)
- continue;
- set_if_valid (map, on_exit[e->src->index], t);
- }
- }
-
- /* Set live on exit for all predecessors of live on entry's. */
- for (i = 0; i < num_var_partitions (map); i++)
- {
- bitmap_iterator bi;
-
- on_entry = live_entry_blocks (liveinfo, i);
- EXECUTE_IF_SET_IN_BITMAP (on_entry, 0, b, bi)
- {
- edge_iterator ei;
- FOR_EACH_EDGE (e, ei, BASIC_BLOCK (b)->preds)
- if (e->src != ENTRY_BLOCK_PTR)
- bitmap_set_bit (on_exit[e->src->index], i);
- }
- }
-
- liveinfo->liveout = on_exit;
-}
-
-
-/* Initialize a tree_partition_associator object using MAP. */
-
-tpa_p
-tpa_init (var_map map)
-{
- tpa_p tpa;
- int num_partitions = num_var_partitions (map);
- int x;
-
- if (num_partitions == 0)
- return NULL;
-
- tpa = (tpa_p) xmalloc (sizeof (struct tree_partition_associator_d));
- tpa->num_trees = 0;
- tpa->uncompressed_num = -1;
- tpa->map = map;
- tpa->next_partition = (int *)xmalloc (num_partitions * sizeof (int));
- memset (tpa->next_partition, TPA_NONE, num_partitions * sizeof (int));
-
- tpa->partition_to_tree_map = (int *)xmalloc (num_partitions * sizeof (int));
- memset (tpa->partition_to_tree_map, TPA_NONE, num_partitions * sizeof (int));
-
- x = MAX (40, (num_partitions / 20));
- VARRAY_TREE_INIT (tpa->trees, x, "trees");
- VARRAY_INT_INIT (tpa->first_partition, x, "first_partition");
-
- return tpa;
-
-}
-
-
-/* Remove PARTITION_INDEX from TREE_INDEX's list in the tpa structure TPA. */
-
-void
-tpa_remove_partition (tpa_p tpa, int tree_index, int partition_index)
-{
- int i;
-
- i = tpa_first_partition (tpa, tree_index);
- if (i == partition_index)
- {
- VARRAY_INT (tpa->first_partition, tree_index) = tpa->next_partition[i];
- }
- else
- {
- for ( ; i != TPA_NONE; i = tpa_next_partition (tpa, i))
- {
- if (tpa->next_partition[i] == partition_index)
- {
- tpa->next_partition[i] = tpa->next_partition[partition_index];
- break;
- }
- }
- }
-}
-
-
-/* Free the memory used by tree_partition_associator object TPA. */
-
-void
-tpa_delete (tpa_p tpa)
-{
- if (!tpa)
- return;
-
- free (tpa->partition_to_tree_map);
- free (tpa->next_partition);
- free (tpa);
-}
-
-
-/* This function will remove any tree entries from TPA which have only a single
- element. This will help keep the size of the conflict graph down. The
- function returns the number of remaining tree lists. */
-
-int
-tpa_compact (tpa_p tpa)
-{
- int last, x, y, first, swap_i;
- tree swap_t;
-
- /* Find the last list which has more than 1 partition. */
- for (last = tpa->num_trees - 1; last > 0; last--)
- {
- first = tpa_first_partition (tpa, last);
- if (tpa_next_partition (tpa, first) != NO_PARTITION)
- break;
- }
-
- x = 0;
- while (x < last)
- {
- first = tpa_first_partition (tpa, x);
-
- /* If there is not more than one partition, swap with the current end
- of the tree list. */
- if (tpa_next_partition (tpa, first) == NO_PARTITION)
- {
- swap_t = VARRAY_TREE (tpa->trees, last);
- swap_i = VARRAY_INT (tpa->first_partition, last);
-
- /* Update the last entry. Since it is known to only have one
- partition, there is nothing else to update. */
- VARRAY_TREE (tpa->trees, last) = VARRAY_TREE (tpa->trees, x);
- VARRAY_INT (tpa->first_partition, last)
- = VARRAY_INT (tpa->first_partition, x);
- tpa->partition_to_tree_map[tpa_first_partition (tpa, last)] = last;
-
- /* Since this list is known to have more than one partition, update
- the list owner entries. */
- VARRAY_TREE (tpa->trees, x) = swap_t;
- VARRAY_INT (tpa->first_partition, x) = swap_i;
- for (y = tpa_first_partition (tpa, x);
- y != NO_PARTITION;
- y = tpa_next_partition (tpa, y))
- tpa->partition_to_tree_map[y] = x;
-
- /* Ensure last is a list with more than one partition. */
- last--;
- for (; last > x; last--)
- {
- first = tpa_first_partition (tpa, last);
- if (tpa_next_partition (tpa, first) != NO_PARTITION)
- break;
- }
- }
- x++;
- }
-
- first = tpa_first_partition (tpa, x);
- if (tpa_next_partition (tpa, first) != NO_PARTITION)
- x++;
- tpa->uncompressed_num = tpa->num_trees;
- tpa->num_trees = x;
- return last;
-}
-
-
-/* Initialize a root_var object with SSA partitions from MAP which are based
- on each root variable. */
-
-root_var_p
-root_var_init (var_map map)
-{
- root_var_p rv;
- int num_partitions = num_var_partitions (map);
- int x, p;
- tree t;
- var_ann_t ann;
- sbitmap seen;
-
- rv = tpa_init (map);
- if (!rv)
- return NULL;
-
- seen = sbitmap_alloc (num_partitions);
- sbitmap_zero (seen);
-
- /* Start at the end and work towards the front. This will provide a list
- that is ordered from smallest to largest. */
- for (x = num_partitions - 1; x >= 0; x--)
- {
- t = partition_to_var (map, x);
-
- /* The var map may not be compacted yet, so check for NULL. */
- if (!t)
- continue;
-
- p = var_to_partition (map, t);
-
- gcc_assert (p != NO_PARTITION);
-
- /* Make sure we only put coalesced partitions into the list once. */
- if (TEST_BIT (seen, p))
- continue;
- SET_BIT (seen, p);
- if (TREE_CODE (t) == SSA_NAME)
- t = SSA_NAME_VAR (t);
- ann = var_ann (t);
- if (ann->root_var_processed)
- {
- rv->next_partition[p] = VARRAY_INT (rv->first_partition,
- VAR_ANN_ROOT_INDEX (ann));
- VARRAY_INT (rv->first_partition, VAR_ANN_ROOT_INDEX (ann)) = p;
- }
- else
- {
- ann->root_var_processed = 1;
- VAR_ANN_ROOT_INDEX (ann) = rv->num_trees++;
- VARRAY_PUSH_TREE (rv->trees, t);
- VARRAY_PUSH_INT (rv->first_partition, p);
- }
- rv->partition_to_tree_map[p] = VAR_ANN_ROOT_INDEX (ann);
- }
-
- /* Reset the out_of_ssa_tag flag on each variable for later use. */
- for (x = 0; x < rv->num_trees; x++)
- {
- t = VARRAY_TREE (rv->trees, x);
- var_ann (t)->root_var_processed = 0;
- }
-
- sbitmap_free (seen);
- return rv;
-}
-
-
-/* Initialize a type_var structure which associates all the partitions in MAP
- of the same type to the type node's index. Volatiles are ignored. */
-
-type_var_p
-type_var_init (var_map map)
-{
- type_var_p tv;
- int x, y, p;
- int num_partitions = num_var_partitions (map);
- tree t;
- sbitmap seen;
-
- seen = sbitmap_alloc (num_partitions);
- sbitmap_zero (seen);
-
- tv = tpa_init (map);
- if (!tv)
- return NULL;
-
- for (x = num_partitions - 1; x >= 0; x--)
- {
- t = partition_to_var (map, x);
-
- /* Disallow coalescing of these types of variables. */
- if (!t
- || TREE_THIS_VOLATILE (t)
- || TREE_CODE (t) == RESULT_DECL
- || TREE_CODE (t) == PARM_DECL
- || (DECL_P (t)
- && (DECL_REGISTER (t)
- || !DECL_IGNORED_P (t)
- || DECL_RTL_SET_P (t))))
- continue;
-
- p = var_to_partition (map, t);
-
- gcc_assert (p != NO_PARTITION);
-
- /* If partitions have been coalesced, only add the representative
- for the partition to the list once. */
- if (TEST_BIT (seen, p))
- continue;
- SET_BIT (seen, p);
- t = TREE_TYPE (t);
-
- /* Find the list for this type. */
- for (y = 0; y < tv->num_trees; y++)
- if (t == VARRAY_TREE (tv->trees, y))
- break;
- if (y == tv->num_trees)
- {
- tv->num_trees++;
- VARRAY_PUSH_TREE (tv->trees, t);
- VARRAY_PUSH_INT (tv->first_partition, p);
- }
- else
- {
- tv->next_partition[p] = VARRAY_INT (tv->first_partition, y);
- VARRAY_INT (tv->first_partition, y) = p;
- }
- tv->partition_to_tree_map[p] = y;
- }
- sbitmap_free (seen);
- return tv;
-}
-
-
-/* Create a new coalesce list object from MAP and return it. */
-
-coalesce_list_p
-create_coalesce_list (var_map map)
-{
- coalesce_list_p list;
-
- list = (coalesce_list_p) xmalloc (sizeof (struct coalesce_list_d));
-
- list->map = map;
- list->add_mode = true;
- list->list = (partition_pair_p *) xcalloc (num_var_partitions (map),
- sizeof (struct partition_pair_d));
- return list;
-}
-
-
-/* Delete coalesce list CL. */
-
-void
-delete_coalesce_list (coalesce_list_p cl)
-{
- free (cl->list);
- free (cl);
-}
-
-
-/* Find a matching coalesce pair object in CL for partitions P1 and P2. If
- one isn't found, return NULL if CREATE is false, otherwise create a new
- coalesce pair object and return it. */
-
-static partition_pair_p
-find_partition_pair (coalesce_list_p cl, int p1, int p2, bool create)
-{
- partition_pair_p node, tmp;
- int s;
-
- /* 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;
- }
- else
- {
- /* This is now the first node in the list. */
- node->next = cl->list[p1];
- cl->list[p1] = node;
- }
-
- return node;
-}
-
-
-/* Add a potential coalesce between P1 and P2 in CL with a cost of VALUE. */
-
-void
-add_coalesce (coalesce_list_p cl, int p1, int p2, int value)
-{
- partition_pair_p node;
-
- gcc_assert (cl->add_mode);
-
- if (p1 == p2)
- return;
-
- node = find_partition_pair (cl, p1, p2, true);
-
- node->cost += value;
-}
-
-
-/* Comparison function to allow qsort to sort P1 and P2 in descending order. */
-
-static
-int compare_pairs (const void *p1, const void *p2)
-{
- return (*(partition_pair_p *)p2)->cost - (*(partition_pair_p *)p1)->cost;
-}
-
-
-/* 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. */
-
-void
-sort_coalesce_list (coalesce_list_p cl)
-{
- int x, num, count;
- partition_pair_p chain, p;
- partition_pair_p *list;
-
- 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;
- }
-
- /* Only call qsort if there are more than 2 items. */
- if (num > 2)
- {
- list = xmalloc (sizeof (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;
- }
- }
- }
-}
-
-
-/* Retrieve the best remaining pair to coalesce from CL. Returns the 2
- partitions via P1 and P2. Their calculated cost is returned by the function.
- NO_BEST_COALESCE is returned if the coalesce list is empty. */
-
-int
-pop_best_coalesce (coalesce_list_p cl, int *p1, int *p2)
-{
- partition_pair_p node;
- int ret;
-
- gcc_assert (!cl->add_mode);
-
- node = cl->list[0];
- if (!node)
- return NO_BEST_COALESCE;
-
- cl->list[0] = node->next;
-
- *p1 = node->first_partition;
- *p2 = node->second_partition;
- ret = node->cost;
- free (node);
-
- return ret;
-}
-
-
-/* If variable VAR is in a partition in MAP, add a conflict in GRAPH between
- VAR and any other live partitions in VEC which are associated via TPA.
- Reset the live bit in VEC. */
-
-static inline void
-add_conflicts_if_valid (tpa_p tpa, conflict_graph graph,
- var_map map, bitmap vec, tree var)
-{
- int p, y, first;
- p = var_to_partition (map, var);
- if (p != NO_PARTITION)
- {
- bitmap_clear_bit (vec, p);
- first = tpa_find_tree (tpa, p);
- /* If find returns nothing, this object isn't interesting. */
- if (first == TPA_NONE)
- return;
- /* Only add interferences between objects in the same list. */
- for (y = tpa_first_partition (tpa, first);
- y != TPA_NONE;
- y = tpa_next_partition (tpa, y))
- {
- if (bitmap_bit_p (vec, y))
- conflict_graph_add (graph, p, y);
- }
- }
-}
-
-
-/* Return a conflict graph for the information contained in LIVE_INFO. Only
- conflicts between items in the same TPA list are added. If optional
- coalesce list CL is passed in, any copies encountered are added. */
-
-conflict_graph
-build_tree_conflict_graph (tree_live_info_p liveinfo, tpa_p tpa,
- coalesce_list_p cl)
-{
- conflict_graph graph;
- var_map map;
- bitmap live;
- int x, y, i;
- basic_block bb;
- varray_type partition_link, tpa_to_clear, tpa_nodes;
- unsigned l;
- ssa_op_iter iter;
- bitmap_iterator bi;
-
- map = live_var_map (liveinfo);
- graph = conflict_graph_new (num_var_partitions (map));
-
- if (tpa_num_trees (tpa) == 0)
- return graph;
-
- live = BITMAP_XMALLOC ();
-
- VARRAY_INT_INIT (partition_link, num_var_partitions (map) + 1, "part_link");
- VARRAY_INT_INIT (tpa_nodes, tpa_num_trees (tpa), "tpa nodes");
- VARRAY_INT_INIT (tpa_to_clear, 50, "tpa to clear");
-
- FOR_EACH_BB (bb)
- {
- block_stmt_iterator bsi;
- tree phi;
-
- /* Start with live on exit temporaries. */
- bitmap_copy (live, live_on_exit (liveinfo, bb));
-
- for (bsi = bsi_last (bb); !bsi_end_p (bsi); bsi_prev (&bsi))
- {
- bool is_a_copy = false;
- tree stmt = bsi_stmt (bsi);
- stmt_ann_t ann;
-
- get_stmt_operands (stmt);
- ann = stmt_ann (stmt);
-
- /* A copy between 2 partitions does not introduce an interference
- by itself. If they did, you would never be able to coalesce
- two things which are copied. If the two variables really do
- conflict, they will conflict elsewhere in the program.
-
- This is handled specially here since we may also be interested
- in copies between real variables and SSA_NAME variables. We may
- be interested in trying to coalesce SSA_NAME variables with
- root variables in some cases. */
-
- if (TREE_CODE (stmt) == MODIFY_EXPR)
- {
- tree lhs = TREE_OPERAND (stmt, 0);
- tree rhs = TREE_OPERAND (stmt, 1);
- int p1, p2;
- int bit;
-
- if (DECL_P (lhs) || TREE_CODE (lhs) == SSA_NAME)
- p1 = var_to_partition (map, lhs);
- else
- p1 = NO_PARTITION;
-
- if (DECL_P (rhs) || TREE_CODE (rhs) == SSA_NAME)
- p2 = var_to_partition (map, rhs);
- else
- p2 = NO_PARTITION;
-
- if (p1 != NO_PARTITION && p2 != NO_PARTITION)
- {
- is_a_copy = true;
- bit = bitmap_bit_p (live, p2);
- /* If the RHS is live, make it not live while we add
- the conflicts, then make it live again. */
- if (bit)
- bitmap_clear_bit (live, p2);
- add_conflicts_if_valid (tpa, graph, map, live, lhs);
- if (bit)
- bitmap_set_bit (live, p2);
- if (cl)
- add_coalesce (cl, p1, p2, 1);
- set_if_valid (map, live, rhs);
- }
- }
-
- if (!is_a_copy)
- {
- tree var;
- FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_DEF)
- {
- add_conflicts_if_valid (tpa, graph, map, live, var);
- }
-
- FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE)
- {
- set_if_valid (map, live, var);
- }
- }
- }
-
- /* If result of a PHI is unused, then the loops over the statements
- will not record any conflicts. However, since the PHI node is
- going to be translated out of SSA form we must record a conflict
- between the result of the PHI and any variables with are live.
- Otherwise the out-of-ssa translation may create incorrect code. */
- for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
- {
- tree result = PHI_RESULT (phi);
- int p = var_to_partition (map, result);
-
- if (p != NO_PARTITION && ! bitmap_bit_p (live, p))
- add_conflicts_if_valid (tpa, graph, map, live, result);
- }
-
- /* Anything which is still live at this point interferes.
- In order to implement this efficiently, only conflicts between
- partitions which have the same TPA root need be added.
- TPA roots which have been seen are tracked in 'tpa_nodes'. A nonzero
- entry points to an index into 'partition_link', which then indexes
- into itself forming a linked list of partitions sharing a tpa root
- which have been seen as live up to this point. Since partitions start
- at index zero, all entries in partition_link are (partition + 1).
-
- Conflicts are added between the current partition and any already seen.
- tpa_clear contains all the tpa_roots processed, and these are the only
- entries which need to be zero'd out for a clean restart. */
-
- EXECUTE_IF_SET_IN_BITMAP (live, 0, x, bi)
- {
- i = tpa_find_tree (tpa, x);
- if (i != TPA_NONE)
- {
- int start = VARRAY_INT (tpa_nodes, i);
- /* If start is 0, a new root reference list is being started.
- Register it to be cleared. */
- if (!start)
- VARRAY_PUSH_INT (tpa_to_clear, i);
-
- /* Add interferences to other tpa members seen. */
- for (y = start; y != 0; y = VARRAY_INT (partition_link, y))
- conflict_graph_add (graph, x, y - 1);
- VARRAY_INT (tpa_nodes, i) = x + 1;
- VARRAY_INT (partition_link, x + 1) = start;
- }
- }
-
- /* Now clear the used tpa root references. */
- for (l = 0; l < VARRAY_ACTIVE_SIZE (tpa_to_clear); l++)
- VARRAY_INT (tpa_nodes, VARRAY_INT (tpa_to_clear, l)) = 0;
- VARRAY_POP_ALL (tpa_to_clear);
- }
-
- BITMAP_XFREE (live);
- return graph;
-}
-
-
-/* This routine will attempt to coalesce the elements in TPA subject to the
- conflicts found in GRAPH. If optional coalesce_list CL is provided,
- only coalesces specified within the coalesce list are attempted. Otherwise
- an attempt is made to coalesce as many partitions within each TPA grouping
- as possible. If DEBUG is provided, debug output will be sent there. */
-
-void
-coalesce_tpa_members (tpa_p tpa, conflict_graph graph, var_map map,
- coalesce_list_p cl, FILE *debug)
-{
- int x, y, z, w;
- tree var, tmp;
-
- /* Attempt to coalesce any items in a coalesce list. */
- if (cl)
- {
- while (pop_best_coalesce (cl, &x, &y) != NO_BEST_COALESCE)
- {
- if (debug)
- {
- fprintf (debug, "Coalesce list: (%d)", x);
- print_generic_expr (debug, partition_to_var (map, x), TDF_SLIM);
- fprintf (debug, " & (%d)", y);
- print_generic_expr (debug, partition_to_var (map, y), TDF_SLIM);
- }
-
- w = tpa_find_tree (tpa, x);
- z = tpa_find_tree (tpa, y);
- if (w != z || w == TPA_NONE || z == TPA_NONE)
- {
- if (debug)
- {
- if (w != z)
- fprintf (debug, ": Fail, Non-matching TPA's\n");
- if (w == TPA_NONE)
- fprintf (debug, ": Fail %d non TPA.\n", x);
- else
- fprintf (debug, ": Fail %d non TPA.\n", y);
- }
- continue;
- }
- var = partition_to_var (map, x);
- tmp = partition_to_var (map, y);
- x = var_to_partition (map, var);
- y = var_to_partition (map, tmp);
- if (debug)
- fprintf (debug, " [map: %d, %d] ", x, y);
- if (x == y)
- {
- if (debug)
- fprintf (debug, ": Already Coalesced.\n");
- continue;
- }
- if (!conflict_graph_conflict_p (graph, x, y))
- {
- z = var_union (map, var, tmp);
- if (z == NO_PARTITION)
- {
- if (debug)
- fprintf (debug, ": Unable to perform partition union.\n");
- continue;
- }
-
- /* z is the new combined partition. We need to remove the other
- partition from the list. Set x to be that other partition. */
- if (z == x)
- {
- conflict_graph_merge_regs (graph, x, y);
- w = tpa_find_tree (tpa, y);
- tpa_remove_partition (tpa, w, y);
- }
- else
- {
- conflict_graph_merge_regs (graph, y, x);
- w = tpa_find_tree (tpa, x);
- tpa_remove_partition (tpa, w, x);
- }
-
- if (debug)
- fprintf (debug, ": Success -> %d\n", z);
- }
- else
- if (debug)
- fprintf (debug, ": Fail due to conflict\n");
- }
- /* If using a coalesce list, don't try to coalesce anything else. */
- return;
- }
-
- for (x = 0; x < tpa_num_trees (tpa); x++)
- {
- while (tpa_first_partition (tpa, x) != TPA_NONE)
- {
- int p1, p2;
- /* Coalesce first partition with anything that doesn't conflict. */
- y = tpa_first_partition (tpa, x);
- tpa_remove_partition (tpa, x, y);
-
- var = partition_to_var (map, y);
- /* p1 is the partition representative to which y belongs. */
- p1 = var_to_partition (map, var);
-
- for (z = tpa_next_partition (tpa, y);
- z != TPA_NONE;
- z = tpa_next_partition (tpa, z))
- {
- tmp = partition_to_var (map, z);
- /* p2 is the partition representative to which z belongs. */
- p2 = var_to_partition (map, tmp);
- if (debug)
- {
- fprintf (debug, "Coalesce : ");
- print_generic_expr (debug, var, TDF_SLIM);
- fprintf (debug, " &");
- print_generic_expr (debug, tmp, TDF_SLIM);
- fprintf (debug, " (%d ,%d)", p1, p2);
- }
-
- /* If partitions are already merged, don't check for conflict. */
- if (tmp == var)
- {
- tpa_remove_partition (tpa, x, z);
- if (debug)
- fprintf (debug, ": Already coalesced\n");
- }
- else
- if (!conflict_graph_conflict_p (graph, p1, p2))
- {
- int v;
- if (tpa_find_tree (tpa, y) == TPA_NONE
- || tpa_find_tree (tpa, z) == TPA_NONE)
- {
- if (debug)
- fprintf (debug, ": Fail non-TPA member\n");
- continue;
- }
- if ((v = var_union (map, var, tmp)) == NO_PARTITION)
- {
- if (debug)
- fprintf (debug, ": Fail cannot combine partitions\n");
- continue;
- }
-
- tpa_remove_partition (tpa, x, z);
- if (v == p1)
- conflict_graph_merge_regs (graph, v, z);
- else
- {
- /* Update the first partition's representative. */
- conflict_graph_merge_regs (graph, v, y);
- p1 = v;
- }
-
- /* The root variable of the partition may be changed
- now. */
- var = partition_to_var (map, p1);
-
- if (debug)
- fprintf (debug, ": Success -> %d\n", v);
- }
- else
- if (debug)
- fprintf (debug, ": Fail, Conflict\n");
- }
- }