2 * This file is part of libFirm.
3 * Copyright (C) 2012 University of Karlsruhe.
8 * @brief More experiments on coalescing.
9 * @author Sebastian Hack
15 #include "lc_opts_enum.h"
23 #include "raw_bitset.h"
26 #include "bitfiddle.h"
28 #include "irgraph_t.h"
33 #include "irnodemap.h"
38 #include "becopyopt.h"
39 #include "becopyopt_t.h"
40 #include "bechordal_t.h"
45 #define DUMP_ALL 2 * DUMP_CLOUD - 1
47 static unsigned dump_flags = 0;
48 static int subtree_iter = 4;
49 static int max_depth = 20;
50 static double constr_factor = 0.9;
52 static const lc_opt_enum_mask_items_t dump_items[] = {
53 { "before", DUMP_BEFORE },
54 { "after", DUMP_AFTER },
55 { "cloud", DUMP_CLOUD },
60 static lc_opt_enum_mask_var_t dump_var = {
61 &dump_flags, dump_items
64 static const lc_opt_table_entry_t options[] = {
65 LC_OPT_ENT_ENUM_MASK("dump", "dump ifg cloud", &dump_var),
66 LC_OPT_ENT_INT ("iter", "iterations for subtree nodes", &subtree_iter),
67 LC_OPT_ENT_DBL ("cf", "factor of constraint importance (between 0.0 and 1.0)", &constr_factor),
68 LC_OPT_ENT_INT ("max", "maximum recursion depth", &max_depth),
74 / ___|| |_ __ _ _ __| |_
75 \___ \| __/ _` | '__| __|
76 ___) | || (_| | | | |_
77 |____/ \__\__,_|_| \__|
81 #define INFEASIBLE(cost) ((cost) == INT_MAX)
83 typedef unsigned col_t;
85 typedef struct co2_irn_t co2_irn_t;
86 typedef struct co2_cloud_t co2_cloud_t;
87 typedef struct co2_cloud_irn_t co2_cloud_irn_t;
98 bitset_t *allocatable_regs;
102 struct list_head cloud_head;
103 DEBUG_ONLY(firm_dbg_module_t *dbg;)
108 affinity_node_t *aff;
109 co2_irn_t *touched_next;
112 int last_color_change;
115 unsigned tmp_fixed : 1;
116 unsigned is_constrained : 1;
117 struct list_head changed_list;
120 struct co2_cloud_irn_t {
121 struct co2_irn_t inh;
125 co2_cloud_irn_t *mst_parent;
128 co2_cloud_irn_t **mst_childs;
133 col_cost_pair_t *tmp_coloring;
134 struct list_head cloud_list;
135 struct list_head mst_list;
150 co2_cloud_irn_t *master;
151 co2_cloud_irn_t *mst_root;
152 co2_cloud_irn_t **seq;
153 struct list_head members_head;
154 struct list_head list;
158 co2_cloud_irn_t *src, *tgt;
162 #define FRONT_BASE(ci,col) ((ci)->fronts + col * (ci)->mst_n_childs)
164 static co2_irn_t *get_co2_irn(co2_t *env, const ir_node *node)
166 co2_irn_t *ci = ir_nodemap_get(co2_irn_t, &env->map, node);
168 ci = OALLOCZ(&env->obst, co2_irn_t);
170 INIT_LIST_HEAD(&ci->changed_list);
171 ci->touched_next = env->touched;
172 ci->orig_col = get_irn_col(node);
177 ir_nodemap_insert(&env->map, node, ci);
182 static co2_cloud_irn_t *get_co2_cloud_irn(co2_t *env, const ir_node *node)
184 co2_cloud_irn_t *ci = ir_nodemap_get(co2_cloud_irn_t, &env->map, node);
186 ci = OALLOCZ(&env->obst, co2_cloud_irn_t);
188 INIT_LIST_HEAD(&ci->inh.changed_list);
189 ci->inh.touched_next = env->touched;
190 ci->inh.orig_col = get_irn_col(node);
191 env->touched = &ci->inh;
193 ci->inh.aff = get_affinity_info(env->co, node);
195 INIT_LIST_HEAD(&ci->cloud_list);
198 ir_nodemap_insert(&env->map, node, ci);
203 #define CLOUD_WEIGHT(c) ((1 - constr_factor) * (c)->costs + constr_factor * (c)->freedom)
205 static int cmp_clouds_gt(const void *a, const void *b)
207 const co2_cloud_t * const *p = (const co2_cloud_t*const*)a;
208 const co2_cloud_t * const *q = (const co2_cloud_t*const*)b;
209 double c = CLOUD_WEIGHT(*p);
210 double d = CLOUD_WEIGHT(*q);
211 return QSORT_CMP(d, c);
215 * An order on color/costs pairs.
216 * If the costs are equal, we use the color as a kind of normalization.
218 static int col_cost_pair_lt(const void *a, const void *b)
220 const col_cost_pair_t *p = (const col_cost_pair_t*)a;
221 const col_cost_pair_t *q = (const col_cost_pair_t*)b;
224 return QSORT_CMP(c, d);
227 static int cmp_edges(const void *a, const void *b)
229 const edge_t *p = (const edge_t*)a;
230 const edge_t *q = (const edge_t*)b;
231 return QSORT_CMP(q->costs, p->costs);
234 static col_t get_col(co2_t *env, const ir_node *irn)
236 co2_irn_t *ci = get_co2_irn(env, irn);
237 return ci->tmp_fixed ? ci->tmp_col : ci->orig_col;
240 static inline int color_is_fix(co2_t *env, const ir_node *irn)
242 co2_irn_t *ci = get_co2_irn(env, irn);
243 return ci->fixed || ci->tmp_fixed;
246 static inline bitset_t *get_adm(co2_t *env, co2_irn_t *ci)
248 if (ci->adm_cache == NULL) {
249 const arch_register_req_t *req;
250 ci->adm_cache = bitset_obstack_alloc(&env->obst, env->n_regs);
251 req = arch_get_irn_register_req(ci->irn);
253 if (arch_register_req_is(req, limited)) {
257 for (i = 0; i < n; ++i) {
258 if (rbitset_is_set(req->limited, i))
259 bitset_set(ci->adm_cache, i);
261 ci->is_constrained = 1;
263 bitset_copy(ci->adm_cache, env->allocatable_regs);
267 return ci->adm_cache;
270 static inline bitset_t *admissible_colors(co2_t *env, co2_irn_t *ci, bitset_t *bs)
272 bitset_copy(bs, get_adm(env, ci));
276 static inline int is_color_admissible(co2_t *env, co2_irn_t *ci, col_t col)
278 bitset_t *bs = get_adm(env, ci);
279 return bitset_is_set(bs, col);
282 static inline int is_constrained(co2_t *env, co2_irn_t *ci)
286 return ci->is_constrained;
289 static void incur_constraint_costs(co2_t *env, const ir_node *irn, col_cost_pair_t *col_costs, int costs)
291 const arch_register_req_t *req = arch_get_irn_register_req(irn);
293 if (arch_register_req_is(req, limited)) {
294 unsigned n_regs = env->co->cls->n_regs;
295 unsigned n_constr = 0;
298 n_constr = rbitset_popcount(req->limited, n_regs);
299 for (i = 0; i < n_regs; ++i) {
300 if (rbitset_is_set(req->limited, i)) {
301 col_costs[i].costs = add_saturated(col_costs[i].costs, costs / n_constr);
308 * Determine costs which shall indicate how cheap/expensive it is to try
309 * to assign a node some color.
310 * The costs are computed for all colors. INT_MAX means that it is impossible
311 * to give the node that specific color.
313 * @param env The co2 this pointer.
314 * @param irn The node.
315 * @param col_costs An array of colors x costs where the costs are written to.
317 static void determine_color_costs(co2_t *env, co2_irn_t *ci, col_cost_pair_t *col_costs)
319 const ir_node *irn = ci->irn;
320 be_ifg_t *ifg = env->co->cenv->ifg;
321 int n_regs = env->co->cls->n_regs;
322 affinity_node_t *a = ci->aff;
324 neighbours_iter_t it;
327 /* Put all forbidden colors into the aux bitset. */
328 bitset_t *const admissible = bitset_alloca(n_regs);
329 admissible_colors(env, ci, admissible);
331 for (i = 0; i < n_regs; ++i) {
332 col_costs[i].col = i;
333 col_costs[i].costs = 0;
337 co_gs_foreach_neighb(a, n) {
338 if (color_is_fix(env, n->irn)) {
339 col_t col = get_col(env, n->irn);
340 col_costs[col].costs = add_saturated(col_costs[col].costs, -n->costs * 128);
343 incur_constraint_costs(env, n->irn, col_costs, -n->costs);
347 be_ifg_foreach_neighbour(ifg, &it, irn, pos) {
348 col_t col = get_col(env, pos);
349 if (color_is_fix(env, pos)) {
350 col_costs[col].costs = INT_MAX;
353 incur_constraint_costs(env, pos, col_costs, INT_MAX);
354 col_costs[col].costs = add_saturated(col_costs[col].costs, 8 * be_ifg_degree(ifg, pos));
357 be_ifg_neighbours_break(&it);
359 /* Set the costs to infinity for each color which is not allowed at this node. */
360 bitset_foreach_clear(admissible, elm) {
361 col_costs[elm].costs = INT_MAX;
366 static void single_color_cost(co2_t *env, co2_irn_t *ci, col_t col, col_cost_pair_t *seq)
368 int n_regs = env->co->cls->n_regs;
371 for (i = 0; i < n_regs; ++i) {
373 seq[i].costs = INT_MAX;
377 assert(is_color_admissible(env, ci, col));
383 static void reject_coloring(struct list_head *h)
385 list_for_each_entry(co2_irn_t, pos, h, changed_list)
389 static void materialize_coloring(struct list_head *h)
391 list_for_each_entry(co2_irn_t, pos, h, changed_list) {
392 pos->orig_col = pos->tmp_col;
397 static int change_color_not(co2_t *env, const ir_node *irn, col_t not_col, struct list_head *parent_changed, int depth);
399 static int recolor(co2_t *env, const ir_node *irn, col_cost_pair_t *col_list, struct list_head *parent_changed, int depth)
401 int n_regs = env->co->cls->n_regs;
402 be_ifg_t *ifg = env->co->cenv->ifg;
403 co2_irn_t *ci = get_co2_irn(env, irn);
408 if (depth >= max_depth)
411 for (i = 0; i < n_regs; ++i) {
412 col_t tgt_col = col_list[i].col;
413 unsigned costs = col_list[i].costs;
416 struct list_head changed;
417 neighbours_iter_t it;
419 DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}trying color %d(%d) on %+F\n", depth, tgt_col, costs, irn));
421 /* If the costs for that color (and all successive) are infinite, bail out we won't make it anyway. */
422 if (INFEASIBLE(costs)) {
423 DB((env->dbg, LEVEL_4, "\t\t%2{firm:indent}color %d infeasible\n", depth, tgt_col));
428 /* Set the new color of the node and mark the node as temporarily fixed. */
429 ci->tmp_col = tgt_col;
433 If that color has costs > 0, there's at least one neighbor having that color,
434 so we will try to change the neighbors' colors, too.
436 INIT_LIST_HEAD(&changed);
437 list_add(&ci->changed_list, &changed);
439 be_ifg_foreach_neighbour(ifg, &it, irn, n) {
441 /* try to re-color the neighbor if it has the target color. */
442 if (get_col(env, n) == tgt_col) {
443 struct list_head tmp;
446 Try to change the color of the neighbor and record all nodes which
447 get changed in the tmp list. Add this list to the "changed" list for
448 that color. If we did not succeed to change the color of the neighbor,
449 we bail out and try the next color.
451 INIT_LIST_HEAD(&tmp);
452 neigh_ok = change_color_not(env, n, tgt_col, &tmp, depth + 1);
453 list_splice(&tmp, &changed);
458 be_ifg_neighbours_break(&it);
461 We managed to assign the target color to all neighbors, so from the perspective
462 of the current node, every thing was ok and we can return safely.
465 DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}color %d(%d) was ok\n", depth, tgt_col, costs));
466 list_splice(&changed, parent_changed);
472 If not, that color did not succeed and we unfix all nodes we touched
473 by traversing the changed list and setting tmp_fixed to 0 for these nodes.
476 reject_coloring(&changed);
482 static int change_color_not(co2_t *env, const ir_node *irn, col_t not_col, struct list_head *parent_changed, int depth)
484 co2_irn_t *ci = get_co2_irn(env, irn);
486 col_t col = get_col(env, irn);
488 DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}clearing %+F(%d) of color %d\n", depth, irn, col, not_col));
490 /* the node does not have to forbidden color. That's fine, mark it as visited and return. */
491 if (col != not_col) {
492 if (!ci->tmp_fixed) {
497 list_add(&ci->changed_list, parent_changed);
501 /* The node has the color it should not have _and_ has not been visited yet. */
502 if (!color_is_fix(env, irn)) {
503 int n_regs = env->co->cls->n_regs;
504 col_cost_pair_t *csts = ALLOCAN(col_cost_pair_t, n_regs);
506 /* Get the costs for giving the node a specific color. */
507 determine_color_costs(env, ci, csts);
509 /* Since the node must not have the not_col, set the costs for that color to "infinity" */
510 csts[not_col].costs = INT_MAX;
512 /* sort the colors according costs, cheapest first. */
513 qsort(csts, n_regs, sizeof(csts[0]), col_cost_pair_lt);
515 /* Try recoloring the node using the color list. */
516 res = recolor(env, irn, csts, parent_changed, depth);
519 /* If we came here, everything went ok. */
523 static int change_color_single(co2_t *env, const ir_node *irn, col_t tgt_col, struct list_head *parent_changed, int depth)
525 co2_irn_t *ci = get_co2_irn(env, irn);
526 col_t col = get_col(env, irn);
529 DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}trying to set %+F(%d) to color %d\n", depth, irn, col, tgt_col));
531 /* the node has the wanted color. That's fine, mark it as visited and return. */
532 if (col == tgt_col) {
533 if (!ci->tmp_fixed) {
536 list_add(&ci->changed_list, parent_changed);
543 if (!color_is_fix(env, irn) && is_color_admissible(env, ci, tgt_col)) {
544 int n_regs = env->co->cls->n_regs;
545 col_cost_pair_t *seq = ALLOCAN(col_cost_pair_t, n_regs);
547 /* Get the costs for giving the node a specific color. */
548 single_color_cost(env, ci, tgt_col, seq);
550 /* Try recoloring the node using the color list. */
551 res = recolor(env, irn, seq, parent_changed, depth);
556 DB((env->dbg, LEVEL_3, "\t\t%2{firm:indent}color %d %s for %+F\n", depth, tgt_col, res ? "was ok" : "failed", irn));
561 * Examine the costs of the current coloring concerning a MST subtree.
562 * @param ci The subtree root.
563 * @param col The color of @p ci.
564 * @return The best coloring for that subtree under the assumption that @p ci has color @p col.
566 static int examine_subtree_coloring(co2_cloud_irn_t *ci, col_t col)
568 int *front = FRONT_BASE(ci, col);
572 for (i = 0; i < ci->mst_n_childs; ++i) {
573 co2_cloud_irn_t *chld = ci->mst_childs[i];
574 col_t chld_col = front[i];
576 cost += examine_subtree_coloring(chld, chld_col);
577 cost += col != chld_col ? chld->mst_costs : 0;
584 * Determine color badnesses of a node.
585 * Badness means that it is unlikely that the node in question can
586 * obtain a color. The higher the badness, the more unlikely it is that
587 * the node can be assigned that color.
588 * @param ci The node.
589 * @param badness An integer array as long as there are registers.
590 * @note The array <code>badness</code> is not cleared.
592 static void node_color_badness(co2_cloud_irn_t *ci, int *badness)
594 co2_t *env = ci->cloud->env;
595 co2_irn_t *ir = &ci->inh;
596 int n_regs = env->n_regs;
597 be_ifg_t *ifg = env->co->cenv->ifg;
598 bitset_t *bs = bitset_alloca(n_regs);
600 neighbours_iter_t it;
602 admissible_colors(env, &ci->inh, bs);
603 bitset_foreach_clear(bs, elm)
604 badness[elm] = ci->costs;
606 /* Use constrained/fixed interfering neighbors to influence the color badness */
607 be_ifg_foreach_neighbour(ifg, &it, ir->irn, irn) {
608 co2_irn_t *ni = get_co2_irn(env, irn);
610 admissible_colors(env, ni, bs);
611 if (bitset_popcount(bs) == 1) {
612 size_t c = bitset_next_set(bs, 0);
613 badness[c] += ci->costs;
616 else if (ni->fixed) {
617 col_t c = get_col(env, ni->irn);
618 badness[c] += ci->costs;
621 be_ifg_neighbours_break(&it);
625 * Determine the badness of a MST subtree.
626 * The badness is written into the <code>color_badness</code> array of each node and accumulated in the parents.
627 * @see node_color_badness() for a definition of badness.
628 * @param ci The root of the subtree.
629 * @param depth Depth for debugging purposes.
631 static void determine_color_badness(co2_cloud_irn_t *ci, int depth)
633 co2_t *env = ci->cloud->env;
636 node_color_badness(ci, ci->color_badness);
638 /* Collect the color badness for the whole subtree */
639 for (i = 0; i < ci->mst_n_childs; ++i) {
640 co2_cloud_irn_t *child = ci->mst_childs[i];
641 determine_color_badness(child, depth + 1);
643 for (j = 0; j < env->n_regs; ++j)
644 ci->color_badness[j] += child->color_badness[j];
647 for (j = 0; j < env->n_regs; ++j)
648 DBG((env->dbg, LEVEL_2, "%2{firm:indent}%+F col %d badness %d\n", depth, ci->inh.irn, j, ci->color_badness[j]));
652 * Unfix all nodes in a MST subtree.
654 static void unfix_subtree(co2_cloud_irn_t *ci)
659 for (i = 0; i < ci->mst_n_childs; ++i)
660 unfix_subtree(ci->mst_childs[i]);
663 static int coalesce_top_down(co2_cloud_irn_t *ci, int child_nr, int depth)
665 co2_t *env = ci->cloud->env;
666 col_cost_pair_t *seq = ALLOCAN(col_cost_pair_t, env->n_regs);
667 int is_root = ci->mst_parent == ci;
668 col_t parent_col = is_root ? (col_t) -1 : get_col(env, ci->mst_parent->inh.irn);
669 int min_badness = INT_MAX;
670 int best_col_costs = INT_MAX;
672 int n_regs = env->n_regs;
673 int n_iter = is_root ? MIN(n_regs, subtree_iter) : 1;
675 struct list_head changed;
678 for (i = 0; i < n_regs; ++i) {
679 int badness = ci->color_badness[i];
682 seq[i].costs = is_color_admissible(env, &ci->inh, i) ? badness : INT_MAX;
684 min_badness = MIN(min_badness, badness);
687 /* If we are not the root and the parent's color is allowed for this node give it top prio. */
688 if (!is_root && is_color_admissible(env, &ci->inh, parent_col))
689 seq[parent_col].costs = min_badness - 1;
691 /* Sort the colors. The will be processed in that ordering. */
692 qsort(seq, env->n_regs, sizeof(seq[0]), col_cost_pair_lt);
694 DBG((env->dbg, LEVEL_2, "\t%2{firm:indent}starting top-down coalesce for %+F\n", depth, ci->inh.irn));
695 INIT_LIST_HEAD(&changed);
696 for (i = 0; i < (best_col < 0 ? n_regs : n_iter); ++i) {
697 col_t col = seq[i].col;
698 int add_cost = !is_root && col != parent_col ? ci->mst_costs : 0;
700 int subtree_costs, sum_costs;
702 DBG((env->dbg, LEVEL_2, "\t%2{firm:indent}%+F trying color %d\n", depth, ci->inh.irn, col));
705 INIT_LIST_HEAD(&changed);
706 ok = change_color_single(env, ci->inh.irn, col, &changed, depth);
708 materialize_coloring(&changed);
715 for (j = 0; j < ci->mst_n_childs; ++j) {
716 co2_cloud_irn_t *child = ci->mst_childs[j];
717 ok = coalesce_top_down(child, j, depth + 1) >= 0;
719 child->inh.fixed = 1;
724 /* If the subtree could not be colored, we have to try another color. */
728 subtree_costs = examine_subtree_coloring(ci, col);
729 sum_costs = subtree_costs + add_cost;
730 DBG((env->dbg, LEVEL_2, "\t%2{firm:indent}-> %+F costing %d + %d is ok.\n", depth, ci->inh.irn, subtree_costs, add_cost));
732 if (sum_costs < best_col_costs) {
734 best_col_costs = sum_costs;
735 ci->col_costs[col] = subtree_costs;
743 int *front = FRONT_BASE(ci->mst_parent, parent_col);
744 front[child_nr] = best_col;
750 static void populate_cloud(co2_t *env, co2_cloud_t *cloud, affinity_node_t *a, int curr_costs)
752 be_ifg_t *ifg = env->co->cenv->ifg;
753 co2_cloud_irn_t *ci = get_co2_cloud_irn(env, a->irn);
759 /* mark the node as visited and add it to the cloud. */
761 list_add(&ci->cloud_list, &cloud->members_head);
763 DB((env->dbg, LEVEL_2, "\t%+F\n", ci->inh.irn));
765 /* determine the nodes costs */
766 co_gs_foreach_neighb(a, n) {
768 DB((env->dbg, LEVEL_3, "\t\tneigh %+F cost %d\n", n->irn, n->costs));
769 if (be_ifg_connected(ifg, a->irn, n->irn))
770 cloud->inevit += n->costs;
773 /* add the node's cost to the total costs of the cloud. */
775 cloud->costs += costs;
776 cloud->n_constr += is_constrained(env, &ci->inh);
777 cloud->freedom += bitset_popcount(get_adm(env, &ci->inh));
778 cloud->max_degree = MAX(cloud->max_degree, ci->inh.aff->degree);
781 /* If this is the heaviest node in the cloud, set it as the cloud's master. */
782 if (costs >= curr_costs) {
787 /* add all the neighbors of the node to the cloud. */
788 co_gs_foreach_neighb(a, n) {
789 affinity_node_t *an = get_affinity_info(env->co, n->irn);
791 populate_cloud(env, cloud, an, curr_costs);
795 static co2_cloud_t *new_cloud(co2_t *env, affinity_node_t *a)
797 co2_cloud_t *cloud = OALLOC(&env->obst, co2_cloud_t);
800 DBG((env->dbg, LEVEL_2, "new cloud with %+F\n", a->irn));
801 memset(cloud, 0, sizeof(cloud[0]));
802 INIT_LIST_HEAD(&cloud->members_head);
803 INIT_LIST_HEAD(&cloud->list);
804 list_add(&cloud->list, &env->cloud_head);
805 cloud->best_costs = INT_MAX;
808 populate_cloud(env, cloud, a, 0);
809 cloud->freedom = (cloud->n_memb * env->n_regs) / cloud->freedom;
811 /* Also allocate space for the node sequence and compute that sequence. */
812 cloud->seq = OALLOCN(&env->obst, co2_cloud_irn_t*, cloud->n_memb);
815 list_for_each_entry(co2_cloud_irn_t, ci, &cloud->members_head, cloud_list) {
817 cloud->seq[i++] = ci;
819 DBG((env->dbg, LEVEL_2, "cloud cost %d, freedom %f\n", cloud->costs, cloud->freedom));
824 static void apply_coloring(co2_cloud_irn_t *ci, col_t col, int depth)
826 const ir_node *irn = ci->inh.irn;
827 int *front = FRONT_BASE(ci, col);
829 struct list_head changed;
831 INIT_LIST_HEAD(&changed);
833 DBG((ci->cloud->env->dbg, LEVEL_2, "%2{firm:indent}setting %+F to %d\n", depth, irn, col));
834 change_color_single(ci->cloud->env, irn, col, &changed, depth);
835 materialize_coloring(&changed);
837 for (i = 0; i < ci->mst_n_childs; ++i) {
838 apply_coloring(ci->mst_childs[i], front[i], depth + 1);
842 static co2_cloud_irn_t *find_mst_root(co2_cloud_irn_t *ci)
844 while (ci != ci->mst_parent)
850 static void process_cloud(co2_cloud_t *cloud)
852 co2_t *env = cloud->env;
853 int n_regs = env->n_regs;
855 int *mst_edges = XMALLOCNZ(int, cloud->n_memb * cloud->n_memb);
862 /* Collect all edges in the cloud on an obstack and sort the increasingly */
863 obstack_init(&cloud->obst);
864 for (i = 0; i < cloud->n_memb; ++i) {
865 co2_cloud_irn_t *ci = cloud->seq[i];
867 co_gs_foreach_neighb(ci->inh.aff, n) {
868 co2_cloud_irn_t *ni = get_co2_cloud_irn(cloud->env, n->irn);
869 if (ci->index < ni->index) {
874 obstack_grow(&cloud->obst, &e, sizeof(e));
879 edges = (edge_t*)obstack_finish(&cloud->obst);
880 qsort(edges, n_edges, sizeof(edges[0]), cmp_edges);
882 /* Compute the maximum spanning tree using Kruskal/Union-Find */
883 DBG((env->dbg, LEVEL_2, "computing spanning tree of cloud with master %+F\n", cloud->master->inh.irn));
884 for (i = 0; i < n_edges; ++i) {
885 edge_t *e = &edges[i];
886 co2_cloud_irn_t *rs = find_mst_root(e->src);
887 co2_cloud_irn_t *rt = find_mst_root(e->tgt);
889 /* if the union/find roots are different */
891 int si = e->src->index;
892 int ti = e->tgt->index;
896 DBG((env->dbg, LEVEL_2, "\tadding edge %+F -- %+F cost %d\n", rs->inh.irn, rt->inh.irn, e->costs));
898 /* this edge is in the MST, so set it in the bitset. */
899 mst_edges[si * cloud->n_memb + ti] = e->costs;
900 mst_edges[ti * cloud->n_memb + si] = e->costs;
903 obstack_free(&cloud->obst, edges);
905 cloud->master->mst_parent = cloud->master;
906 cloud->mst_root = cloud->master;
907 q = new_pdeq1(cloud->master);
908 while (!pdeq_empty(q)) {
909 co2_cloud_irn_t *ci = (co2_cloud_irn_t*)pdeq_getl(q);
910 int ofs = ci->index * cloud->n_memb;
911 int end = ofs + cloud->n_memb;
914 ci->mst_n_childs = 0;
915 for (i = ofs; i < end; ++i) {
916 if (mst_edges[i] != 0) {
918 co2_cloud_irn_t *child = cloud->seq[i - ofs];
920 /* put the child to the worklist */
923 /* make ci the parent of the child and add the child to the children array of the parent */
924 child->mst_parent = ci;
925 child->mst_costs = mst_edges[i];
927 obstack_ptr_grow(&cloud->obst, child);
929 mst_edges[other * cloud->n_memb + ci->index] = 0;
934 obstack_ptr_grow(&cloud->obst, NULL);
935 ci->mst_childs = (co2_cloud_irn_t**)obstack_finish(&cloud->obst);
941 DBG((env->dbg, LEVEL_3, "mst:\n"));
942 for (i = 0; i < cloud->n_memb; ++i) {
943 DEBUG_ONLY(co2_cloud_irn_t *ci = cloud->seq[i];)
944 DBG((env->dbg, LEVEL_3, "\t%+F -> %+F\n", ci->inh.irn, ci->mst_parent->inh.irn));
947 for (i = 0; i < cloud->n_memb; ++i) {
948 co2_cloud_irn_t *ci = cloud->seq[i];
949 int n_childs = ci->mst_n_childs;
952 ci->col_costs = OALLOCNZ(&cloud->obst, int, n_regs);
953 ci->tmp_coloring = OALLOCNZ(&cloud->obst, col_cost_pair_t, n_regs);
954 ci->fronts = OALLOCNZ(&cloud->obst, int, n_regs * n_childs);
955 ci->color_badness = OALLOCNZ(&cloud->obst, int, n_regs);
957 for (j = 0; j < env->n_regs; j++)
958 ci->col_costs[j] = INT_MAX;
961 determine_color_badness(cloud->mst_root, 0);
962 best_col = coalesce_top_down(cloud->mst_root, -1, 0);
963 unfix_subtree(cloud->mst_root);
964 apply_coloring(cloud->mst_root, best_col, 0);
966 /* The coloring should represent the one with the best costs. */
967 //materialize_coloring(&changed);
968 DBG((env->dbg, LEVEL_2, "\tbest coloring for root %+F was %d costing %d\n",
969 cloud->mst_root->inh.irn, best_col, examine_subtree_coloring(cloud->mst_root, best_col)));
971 /* Fix all nodes in the cloud. */
972 for (i = 0; i < cloud->n_memb; ++i)
973 cloud->seq[i]->inh.fixed = 1;
975 /* Free all space used while optimizing this cloud. */
976 obstack_free(&cloud->obst, NULL);
979 static int cloud_costs(co2_cloud_t *cloud)
983 for (i = 0; i < cloud->n_memb; ++i) {
984 co2_irn_t *ci = (co2_irn_t *) cloud->seq[i];
985 col_t col = get_col(cloud->env, ci->irn);
986 co_gs_foreach_neighb(ci->aff, n) {
987 col_t n_col = get_col(cloud->env, n->irn);
988 costs += col != n_col ? n->costs : 0;
995 static void writeback_colors(co2_t *env)
999 for (irn = env->touched; irn; irn = irn->touched_next) {
1000 const arch_register_t *reg = arch_register_for_index(env->co->cls, irn->orig_col);
1001 arch_set_irn_register((ir_node*)irn->irn, reg);
1005 static void process(co2_t *env)
1007 co2_cloud_t **clouds;
1012 int final_costs = 0;
1015 co_gs_foreach_aff_node(env->co, a) {
1016 co2_cloud_irn_t *ci = get_co2_cloud_irn(env, a->irn);
1025 clouds = XMALLOCN(co2_cloud_t*, n_clouds);
1026 list_for_each_entry(co2_cloud_t, pos, &env->cloud_head, list)
1028 qsort(clouds, n_clouds, sizeof(clouds[0]), cmp_clouds_gt);
1030 for (i = 0; i < n_clouds; ++i) {
1031 init_costs += cloud_costs(clouds[i]);
1033 /* Process the cloud. */
1034 process_cloud(clouds[i]);
1036 all_costs += clouds[i]->costs;
1037 final_costs += cloud_costs(clouds[i]);
1040 DB((env->dbg, LEVEL_1, "all costs: %d, init costs: %d, final costs: %d\n", all_costs, init_costs, final_costs));
1045 static int co_solve_heuristic_new(copy_opt_t *co)
1049 ir_nodemap_init(&env.map, co->irg);
1050 obstack_init(&env.obst);
1054 env.n_regs = co->cls->n_regs;
1055 env.allocatable_regs = bitset_alloca(co->cls->n_regs);
1056 be_put_allocatable_regs(co->cenv->irg, co->cls, env.allocatable_regs);
1057 FIRM_DBG_REGISTER(env.dbg, "firm.be.co2");
1058 INIT_LIST_HEAD(&env.cloud_head);
1062 writeback_colors(&env);
1063 obstack_free(&env.obst, NULL);
1064 ir_nodemap_destroy(&env.map);
1068 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_copyheur2)
1069 void be_init_copyheur2(void)
1071 lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
1072 lc_opt_entry_t *ra_grp = lc_opt_get_grp(be_grp, "ra");
1073 lc_opt_entry_t *chordal_grp = lc_opt_get_grp(ra_grp, "chordal");
1074 lc_opt_entry_t *co2_grp = lc_opt_get_grp(chordal_grp, "co2");
1076 static co_algo_info copyheur = {
1077 co_solve_heuristic_new, 0
1080 lc_opt_add_table(co2_grp, options);
1081 be_register_copyopt("heur2", ©heur);