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"
20 #include "beintlive_t.h"
25 #include "raw_bitset.h"
28 #include "bitfiddle.h"
30 #include "irgraph_t.h"
35 #include "irnodemap.h"
40 #include "becopyopt.h"
41 #include "becopyopt_t.h"
42 #include "bechordal_t.h"
47 #define DUMP_ALL 2 * DUMP_CLOUD - 1
49 static unsigned dump_flags = 0;
50 static int subtree_iter = 4;
51 static int max_depth = 20;
52 static double constr_factor = 0.9;
54 static const lc_opt_enum_mask_items_t dump_items[] = {
55 { "before", DUMP_BEFORE },
56 { "after", DUMP_AFTER },
57 { "cloud", DUMP_CLOUD },
62 static lc_opt_enum_mask_var_t dump_var = {
63 &dump_flags, dump_items
66 static const lc_opt_table_entry_t options[] = {
67 LC_OPT_ENT_ENUM_MASK("dump", "dump ifg cloud", &dump_var),
68 LC_OPT_ENT_INT ("iter", "iterations for subtree nodes", &subtree_iter),
69 LC_OPT_ENT_DBL ("cf", "factor of constraint importance (between 0.0 and 1.0)", &constr_factor),
70 LC_OPT_ENT_INT ("max", "maximum recursion depth", &max_depth),
76 / ___|| |_ __ _ _ __| |_
77 \___ \| __/ _` | '__| __|
78 ___) | || (_| | | | |_
79 |____/ \__\__,_|_| \__|
83 #define INFEASIBLE(cost) ((cost) == INT_MAX)
85 typedef unsigned col_t;
87 typedef struct co2_irn_t co2_irn_t;
88 typedef struct co2_cloud_t co2_cloud_t;
89 typedef struct co2_cloud_irn_t co2_cloud_irn_t;
100 bitset_t *allocatable_regs;
104 struct list_head cloud_head;
105 DEBUG_ONLY(firm_dbg_module_t *dbg;)
110 affinity_node_t *aff;
111 co2_irn_t *touched_next;
116 unsigned tmp_fixed : 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;
148 co2_cloud_irn_t *master;
149 co2_cloud_irn_t *mst_root;
150 co2_cloud_irn_t **seq;
151 struct list_head members_head;
152 struct list_head list;
156 co2_cloud_irn_t *src, *tgt;
160 #define FRONT_BASE(ci,col) ((ci)->fronts + col * (ci)->mst_n_childs)
162 static co2_irn_t *get_co2_irn(co2_t *env, const ir_node *node)
164 co2_irn_t *ci = ir_nodemap_get(co2_irn_t, &env->map, node);
166 ci = OALLOCZ(&env->obst, co2_irn_t);
168 INIT_LIST_HEAD(&ci->changed_list);
169 ci->touched_next = env->touched;
170 ci->orig_col = get_irn_col(node);
175 ir_nodemap_insert(&env->map, node, ci);
180 static co2_cloud_irn_t *get_co2_cloud_irn(co2_t *env, const ir_node *node)
182 co2_cloud_irn_t *ci = ir_nodemap_get(co2_cloud_irn_t, &env->map, node);
184 ci = OALLOCZ(&env->obst, co2_cloud_irn_t);
186 INIT_LIST_HEAD(&ci->inh.changed_list);
187 ci->inh.touched_next = env->touched;
188 ci->inh.orig_col = get_irn_col(node);
189 env->touched = &ci->inh;
191 ci->inh.aff = get_affinity_info(env->co, node);
193 INIT_LIST_HEAD(&ci->cloud_list);
196 ir_nodemap_insert(&env->map, node, ci);
201 #define CLOUD_WEIGHT(c) ((1 - constr_factor) * (c)->costs + constr_factor * (c)->freedom)
203 static int cmp_clouds_gt(const void *a, const void *b)
205 const co2_cloud_t * const *p = (const co2_cloud_t*const*)a;
206 const co2_cloud_t * const *q = (const co2_cloud_t*const*)b;
207 double c = CLOUD_WEIGHT(*p);
208 double d = CLOUD_WEIGHT(*q);
209 return QSORT_CMP(d, c);
213 * An order on color/costs pairs.
214 * If the costs are equal, we use the color as a kind of normalization.
216 static int col_cost_pair_lt(const void *a, const void *b)
218 const col_cost_pair_t *p = (const col_cost_pair_t*)a;
219 const col_cost_pair_t *q = (const col_cost_pair_t*)b;
222 return QSORT_CMP(c, d);
225 static int cmp_edges(const void *a, const void *b)
227 const edge_t *p = (const edge_t*)a;
228 const edge_t *q = (const edge_t*)b;
229 return QSORT_CMP(q->costs, p->costs);
232 static col_t get_col(co2_t *env, const ir_node *irn)
234 co2_irn_t *ci = get_co2_irn(env, irn);
235 return ci->tmp_fixed ? ci->tmp_col : ci->orig_col;
238 static inline int color_is_fix(co2_t *env, const ir_node *irn)
240 co2_irn_t *ci = get_co2_irn(env, irn);
241 return ci->fixed || ci->tmp_fixed;
244 static inline bitset_t const *admissible_colors(co2_t *const env, co2_irn_t *const ci)
246 if (ci->adm_cache == NULL) {
247 const arch_register_req_t *req;
248 ci->adm_cache = bitset_obstack_alloc(&env->obst, env->n_regs);
249 req = arch_get_irn_register_req(ci->irn);
251 if (arch_register_req_is(req, limited)) {
252 rbitset_copy_to_bitset(req->limited, ci->adm_cache);
254 bitset_copy(ci->adm_cache, env->allocatable_regs);
258 return ci->adm_cache;
261 static inline int is_color_admissible(co2_t *env, co2_irn_t *ci, col_t col)
263 bitset_t const *const bs = admissible_colors(env, ci);
264 return bitset_is_set(bs, col);
267 static void incur_constraint_costs(ir_node const *const irn, col_cost_pair_t *const col_costs, int const costs)
269 const arch_register_req_t *req = arch_get_irn_register_req(irn);
271 if (arch_register_req_is(req, limited)) {
272 unsigned const n_regs = req->cls->n_regs;
273 unsigned const n_constr = rbitset_popcount(req->limited, n_regs);
274 for (unsigned i = 0; i < n_regs; ++i) {
275 if (rbitset_is_set(req->limited, i)) {
276 col_costs[i].costs = add_saturated(col_costs[i].costs, costs / n_constr);
283 * Determine costs which shall indicate how cheap/expensive it is to try
284 * to assign a node some color.
285 * The costs are computed for all colors. INT_MAX means that it is impossible
286 * to give the node that specific color.
288 * @param env The co2 this pointer.
289 * @param irn The node.
290 * @param col_costs An array of colors x costs where the costs are written to.
292 static void determine_color_costs(co2_t *env, co2_irn_t *ci, col_cost_pair_t *col_costs)
294 const ir_node *irn = ci->irn;
295 be_ifg_t *ifg = env->co->cenv->ifg;
296 int n_regs = env->co->cls->n_regs;
297 affinity_node_t *a = ci->aff;
299 neighbours_iter_t it;
302 for (i = 0; i < n_regs; ++i) {
303 col_costs[i].col = i;
304 col_costs[i].costs = 0;
308 co_gs_foreach_neighb(a, n) {
309 if (color_is_fix(env, n->irn)) {
310 col_t col = get_col(env, n->irn);
311 col_costs[col].costs = add_saturated(col_costs[col].costs, -n->costs * 128);
314 incur_constraint_costs(n->irn, col_costs, -n->costs);
318 be_ifg_foreach_neighbour(ifg, &it, irn, pos) {
319 col_t col = get_col(env, pos);
320 if (color_is_fix(env, pos)) {
321 col_costs[col].costs = INT_MAX;
324 incur_constraint_costs(pos, col_costs, INT_MAX);
325 col_costs[col].costs = add_saturated(col_costs[col].costs, 8 * be_ifg_degree(ifg, pos));
328 be_ifg_neighbours_break(&it);
330 /* Set the costs to infinity for each color which is not allowed at this node. */
331 bitset_t const *const admissible = admissible_colors(env, ci);
332 bitset_foreach_clear(admissible, elm) {
333 col_costs[elm].costs = INT_MAX;
337 static void single_color_cost(co2_t *env, co2_irn_t *ci, col_t col, col_cost_pair_t *seq)
339 int n_regs = env->co->cls->n_regs;
342 for (i = 0; i < n_regs; ++i) {
344 seq[i].costs = INT_MAX;
348 assert(is_color_admissible(env, ci, col));
354 static void reject_coloring(struct list_head *h)
356 list_for_each_entry(co2_irn_t, pos, h, changed_list)
360 static void materialize_coloring(struct list_head *h)
362 list_for_each_entry(co2_irn_t, pos, h, changed_list) {
363 pos->orig_col = pos->tmp_col;
368 static int change_color_not(co2_t *env, const ir_node *irn, col_t not_col, struct list_head *parent_changed, int depth);
370 static int recolor(co2_t *env, const ir_node *irn, col_cost_pair_t *col_list, struct list_head *parent_changed, int depth)
372 int n_regs = env->co->cls->n_regs;
373 be_ifg_t *ifg = env->co->cenv->ifg;
374 co2_irn_t *ci = get_co2_irn(env, irn);
379 if (depth >= max_depth)
382 for (i = 0; i < n_regs; ++i) {
383 col_t tgt_col = col_list[i].col;
384 unsigned costs = col_list[i].costs;
387 struct list_head changed;
388 neighbours_iter_t it;
390 DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}trying color %d(%d) on %+F\n", depth, tgt_col, costs, irn));
392 /* If the costs for that color (and all successive) are infinite, bail out we won't make it anyway. */
393 if (INFEASIBLE(costs)) {
394 DB((env->dbg, LEVEL_4, "\t\t%2{firm:indent}color %d infeasible\n", depth, tgt_col));
399 /* Set the new color of the node and mark the node as temporarily fixed. */
400 ci->tmp_col = tgt_col;
404 If that color has costs > 0, there's at least one neighbor having that color,
405 so we will try to change the neighbors' colors, too.
407 INIT_LIST_HEAD(&changed);
408 list_add(&ci->changed_list, &changed);
410 be_ifg_foreach_neighbour(ifg, &it, irn, n) {
412 /* try to re-color the neighbor if it has the target color. */
413 if (get_col(env, n) == tgt_col) {
414 struct list_head tmp;
417 Try to change the color of the neighbor and record all nodes which
418 get changed in the tmp list. Add this list to the "changed" list for
419 that color. If we did not succeed to change the color of the neighbor,
420 we bail out and try the next color.
422 INIT_LIST_HEAD(&tmp);
423 neigh_ok = change_color_not(env, n, tgt_col, &tmp, depth + 1);
424 list_splice(&tmp, &changed);
429 be_ifg_neighbours_break(&it);
432 We managed to assign the target color to all neighbors, so from the perspective
433 of the current node, every thing was ok and we can return safely.
436 DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}color %d(%d) was ok\n", depth, tgt_col, costs));
437 list_splice(&changed, parent_changed);
443 If not, that color did not succeed and we unfix all nodes we touched
444 by traversing the changed list and setting tmp_fixed to 0 for these nodes.
447 reject_coloring(&changed);
453 static int change_color_not(co2_t *env, const ir_node *irn, col_t not_col, struct list_head *parent_changed, int depth)
455 co2_irn_t *ci = get_co2_irn(env, irn);
457 col_t col = get_col(env, irn);
459 DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}clearing %+F(%d) of color %d\n", depth, irn, col, not_col));
461 /* the node does not have to forbidden color. That's fine, mark it as visited and return. */
462 if (col != not_col) {
463 if (!ci->tmp_fixed) {
468 list_add(&ci->changed_list, parent_changed);
472 /* The node has the color it should not have _and_ has not been visited yet. */
473 if (!color_is_fix(env, irn)) {
474 int n_regs = env->co->cls->n_regs;
475 col_cost_pair_t *csts = ALLOCAN(col_cost_pair_t, n_regs);
477 /* Get the costs for giving the node a specific color. */
478 determine_color_costs(env, ci, csts);
480 /* Since the node must not have the not_col, set the costs for that color to "infinity" */
481 csts[not_col].costs = INT_MAX;
483 /* sort the colors according costs, cheapest first. */
484 qsort(csts, n_regs, sizeof(csts[0]), col_cost_pair_lt);
486 /* Try recoloring the node using the color list. */
487 res = recolor(env, irn, csts, parent_changed, depth);
490 /* If we came here, everything went ok. */
494 static int change_color_single(co2_t *env, const ir_node *irn, col_t tgt_col, struct list_head *parent_changed, int depth)
496 co2_irn_t *ci = get_co2_irn(env, irn);
497 col_t col = get_col(env, irn);
500 DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}trying to set %+F(%d) to color %d\n", depth, irn, col, tgt_col));
502 /* the node has the wanted color. That's fine, mark it as visited and return. */
503 if (col == tgt_col) {
504 if (!ci->tmp_fixed) {
507 list_add(&ci->changed_list, parent_changed);
514 if (!color_is_fix(env, irn) && is_color_admissible(env, ci, tgt_col)) {
515 int n_regs = env->co->cls->n_regs;
516 col_cost_pair_t *seq = ALLOCAN(col_cost_pair_t, n_regs);
518 /* Get the costs for giving the node a specific color. */
519 single_color_cost(env, ci, tgt_col, seq);
521 /* Try recoloring the node using the color list. */
522 res = recolor(env, irn, seq, parent_changed, depth);
527 DB((env->dbg, LEVEL_3, "\t\t%2{firm:indent}color %d %s for %+F\n", depth, tgt_col, res ? "was ok" : "failed", irn));
532 * Examine the costs of the current coloring concerning a MST subtree.
533 * @param ci The subtree root.
534 * @param col The color of @p ci.
535 * @return The best coloring for that subtree under the assumption that @p ci has color @p col.
537 static int examine_subtree_coloring(co2_cloud_irn_t *ci, col_t col)
539 int *front = FRONT_BASE(ci, col);
543 for (i = 0; i < ci->mst_n_childs; ++i) {
544 co2_cloud_irn_t *chld = ci->mst_childs[i];
545 col_t chld_col = front[i];
547 cost += examine_subtree_coloring(chld, chld_col);
548 cost += col != chld_col ? chld->mst_costs : 0;
555 * Determine color badnesses of a node.
556 * Badness means that it is unlikely that the node in question can
557 * obtain a color. The higher the badness, the more unlikely it is that
558 * the node can be assigned that color.
559 * @param ci The node.
560 * @param badness An integer array as long as there are registers.
561 * @note The array <code>badness</code> is not cleared.
563 static void node_color_badness(co2_cloud_irn_t *ci, int *badness)
565 co2_t *env = ci->cloud->env;
566 co2_irn_t *ir = &ci->inh;
567 be_ifg_t *ifg = env->co->cenv->ifg;
569 neighbours_iter_t it;
572 bitset_t const *const bs = admissible_colors(env, &ci->inh);
573 bitset_foreach_clear(bs, elm)
574 badness[elm] = ci->costs;
577 /* Use constrained/fixed interfering neighbors to influence the color badness */
578 be_ifg_foreach_neighbour(ifg, &it, ir->irn, irn) {
579 co2_irn_t *ni = get_co2_irn(env, irn);
581 bitset_t const *const bs = admissible_colors(env, ni);
582 if (bitset_popcount(bs) == 1) {
583 size_t c = bitset_next_set(bs, 0);
584 badness[c] += ci->costs;
587 else if (ni->fixed) {
588 col_t c = get_col(env, ni->irn);
589 badness[c] += ci->costs;
592 be_ifg_neighbours_break(&it);
596 * Determine the badness of a MST subtree.
597 * The badness is written into the <code>color_badness</code> array of each node and accumulated in the parents.
598 * @see node_color_badness() for a definition of badness.
599 * @param ci The root of the subtree.
600 * @param depth Depth for debugging purposes.
602 static void determine_color_badness(co2_cloud_irn_t *ci, int depth)
604 co2_t *env = ci->cloud->env;
607 node_color_badness(ci, ci->color_badness);
609 /* Collect the color badness for the whole subtree */
610 for (i = 0; i < ci->mst_n_childs; ++i) {
611 co2_cloud_irn_t *child = ci->mst_childs[i];
612 determine_color_badness(child, depth + 1);
614 for (j = 0; j < env->n_regs; ++j)
615 ci->color_badness[j] += child->color_badness[j];
618 for (j = 0; j < env->n_regs; ++j)
619 DBG((env->dbg, LEVEL_2, "%2{firm:indent}%+F col %d badness %d\n", depth, ci->inh.irn, j, ci->color_badness[j]));
623 * Unfix all nodes in a MST subtree.
625 static void unfix_subtree(co2_cloud_irn_t *ci)
630 for (i = 0; i < ci->mst_n_childs; ++i)
631 unfix_subtree(ci->mst_childs[i]);
634 static int coalesce_top_down(co2_cloud_irn_t *ci, int child_nr, int depth)
636 co2_t *env = ci->cloud->env;
637 col_cost_pair_t *seq = ALLOCAN(col_cost_pair_t, env->n_regs);
638 int is_root = ci->mst_parent == ci;
639 col_t parent_col = is_root ? (col_t) -1 : get_col(env, ci->mst_parent->inh.irn);
640 int min_badness = INT_MAX;
641 int best_col_costs = INT_MAX;
643 int n_regs = env->n_regs;
644 int n_iter = is_root ? MIN(n_regs, subtree_iter) : 1;
646 struct list_head changed;
649 for (i = 0; i < n_regs; ++i) {
650 int badness = ci->color_badness[i];
653 seq[i].costs = is_color_admissible(env, &ci->inh, i) ? badness : INT_MAX;
655 min_badness = MIN(min_badness, badness);
658 /* If we are not the root and the parent's color is allowed for this node give it top prio. */
659 if (!is_root && is_color_admissible(env, &ci->inh, parent_col))
660 seq[parent_col].costs = min_badness - 1;
662 /* Sort the colors. The will be processed in that ordering. */
663 qsort(seq, env->n_regs, sizeof(seq[0]), col_cost_pair_lt);
665 DBG((env->dbg, LEVEL_2, "\t%2{firm:indent}starting top-down coalesce for %+F\n", depth, ci->inh.irn));
666 INIT_LIST_HEAD(&changed);
667 for (i = 0; i < (best_col < 0 ? n_regs : n_iter); ++i) {
668 col_t col = seq[i].col;
669 int add_cost = !is_root && col != parent_col ? ci->mst_costs : 0;
671 int subtree_costs, sum_costs;
673 DBG((env->dbg, LEVEL_2, "\t%2{firm:indent}%+F trying color %d\n", depth, ci->inh.irn, col));
676 INIT_LIST_HEAD(&changed);
677 ok = change_color_single(env, ci->inh.irn, col, &changed, depth);
679 materialize_coloring(&changed);
686 for (j = 0; j < ci->mst_n_childs; ++j) {
687 co2_cloud_irn_t *child = ci->mst_childs[j];
688 ok = coalesce_top_down(child, j, depth + 1) >= 0;
690 child->inh.fixed = 1;
695 /* If the subtree could not be colored, we have to try another color. */
699 subtree_costs = examine_subtree_coloring(ci, col);
700 sum_costs = subtree_costs + add_cost;
701 DBG((env->dbg, LEVEL_2, "\t%2{firm:indent}-> %+F costing %d + %d is ok.\n", depth, ci->inh.irn, subtree_costs, add_cost));
703 if (sum_costs < best_col_costs) {
705 best_col_costs = sum_costs;
706 ci->col_costs[col] = subtree_costs;
714 int *front = FRONT_BASE(ci->mst_parent, parent_col);
715 front[child_nr] = best_col;
721 static void populate_cloud(co2_t *env, co2_cloud_t *cloud, affinity_node_t *a, int curr_costs)
723 co2_cloud_irn_t *ci = get_co2_cloud_irn(env, a->irn);
729 /* mark the node as visited and add it to the cloud. */
731 list_add(&ci->cloud_list, &cloud->members_head);
733 DB((env->dbg, LEVEL_2, "\t%+F\n", ci->inh.irn));
735 /* determine the nodes costs */
736 be_lv_t *const lv = be_get_irg_liveness(env->co->irg);
737 co_gs_foreach_neighb(a, n) {
739 DB((env->dbg, LEVEL_3, "\t\tneigh %+F cost %d\n", n->irn, n->costs));
740 if (be_values_interfere(lv, a->irn, n->irn))
741 cloud->inevit += n->costs;
744 /* add the node's cost to the total costs of the cloud. */
746 cloud->costs += costs;
747 cloud->freedom += bitset_popcount(admissible_colors(env, &ci->inh));
750 /* If this is the heaviest node in the cloud, set it as the cloud's master. */
751 if (costs >= curr_costs) {
756 /* add all the neighbors of the node to the cloud. */
757 co_gs_foreach_neighb(a, n) {
758 affinity_node_t *an = get_affinity_info(env->co, n->irn);
760 populate_cloud(env, cloud, an, curr_costs);
764 static co2_cloud_t *new_cloud(co2_t *env, affinity_node_t *a)
766 co2_cloud_t *cloud = OALLOC(&env->obst, co2_cloud_t);
769 DBG((env->dbg, LEVEL_2, "new cloud with %+F\n", a->irn));
770 memset(cloud, 0, sizeof(cloud[0]));
771 INIT_LIST_HEAD(&cloud->members_head);
772 INIT_LIST_HEAD(&cloud->list);
773 list_add(&cloud->list, &env->cloud_head);
774 cloud->best_costs = INT_MAX;
777 populate_cloud(env, cloud, a, 0);
778 cloud->freedom = (cloud->n_memb * env->n_regs) / cloud->freedom;
780 /* Also allocate space for the node sequence and compute that sequence. */
781 cloud->seq = OALLOCN(&env->obst, co2_cloud_irn_t*, cloud->n_memb);
784 list_for_each_entry(co2_cloud_irn_t, ci, &cloud->members_head, cloud_list) {
786 cloud->seq[i++] = ci;
788 DBG((env->dbg, LEVEL_2, "cloud cost %d, freedom %f\n", cloud->costs, cloud->freedom));
793 static void apply_coloring(co2_cloud_irn_t *ci, col_t col, int depth)
795 const ir_node *irn = ci->inh.irn;
796 int *front = FRONT_BASE(ci, col);
798 struct list_head changed;
800 INIT_LIST_HEAD(&changed);
802 DBG((ci->cloud->env->dbg, LEVEL_2, "%2{firm:indent}setting %+F to %d\n", depth, irn, col));
803 change_color_single(ci->cloud->env, irn, col, &changed, depth);
804 materialize_coloring(&changed);
806 for (i = 0; i < ci->mst_n_childs; ++i) {
807 apply_coloring(ci->mst_childs[i], front[i], depth + 1);
811 static co2_cloud_irn_t *find_mst_root(co2_cloud_irn_t *ci)
813 while (ci != ci->mst_parent)
819 static void process_cloud(co2_cloud_t *cloud)
821 co2_t *env = cloud->env;
822 int n_regs = env->n_regs;
824 int *mst_edges = XMALLOCNZ(int, cloud->n_memb * cloud->n_memb);
831 /* Collect all edges in the cloud on an obstack and sort the increasingly */
832 obstack_init(&cloud->obst);
833 for (i = 0; i < cloud->n_memb; ++i) {
834 co2_cloud_irn_t *ci = cloud->seq[i];
836 co_gs_foreach_neighb(ci->inh.aff, n) {
837 co2_cloud_irn_t *ni = get_co2_cloud_irn(cloud->env, n->irn);
838 if (ci->index < ni->index) {
843 obstack_grow(&cloud->obst, &e, sizeof(e));
848 edges = (edge_t*)obstack_finish(&cloud->obst);
849 qsort(edges, n_edges, sizeof(edges[0]), cmp_edges);
851 /* Compute the maximum spanning tree using Kruskal/Union-Find */
852 DBG((env->dbg, LEVEL_2, "computing spanning tree of cloud with master %+F\n", cloud->master->inh.irn));
853 for (i = 0; i < n_edges; ++i) {
854 edge_t *e = &edges[i];
855 co2_cloud_irn_t *rs = find_mst_root(e->src);
856 co2_cloud_irn_t *rt = find_mst_root(e->tgt);
858 /* if the union/find roots are different */
860 int si = e->src->index;
861 int ti = e->tgt->index;
865 DBG((env->dbg, LEVEL_2, "\tadding edge %+F -- %+F cost %d\n", rs->inh.irn, rt->inh.irn, e->costs));
867 /* this edge is in the MST, so set it in the bitset. */
868 mst_edges[si * cloud->n_memb + ti] = e->costs;
869 mst_edges[ti * cloud->n_memb + si] = e->costs;
872 obstack_free(&cloud->obst, edges);
874 cloud->master->mst_parent = cloud->master;
875 cloud->mst_root = cloud->master;
876 q = new_pdeq1(cloud->master);
877 while (!pdeq_empty(q)) {
878 co2_cloud_irn_t *ci = (co2_cloud_irn_t*)pdeq_getl(q);
879 int ofs = ci->index * cloud->n_memb;
880 int end = ofs + cloud->n_memb;
883 ci->mst_n_childs = 0;
884 for (i = ofs; i < end; ++i) {
885 if (mst_edges[i] != 0) {
887 co2_cloud_irn_t *child = cloud->seq[i - ofs];
889 /* put the child to the worklist */
892 /* make ci the parent of the child and add the child to the children array of the parent */
893 child->mst_parent = ci;
894 child->mst_costs = mst_edges[i];
896 obstack_ptr_grow(&cloud->obst, child);
898 mst_edges[other * cloud->n_memb + ci->index] = 0;
903 obstack_ptr_grow(&cloud->obst, NULL);
904 ci->mst_childs = (co2_cloud_irn_t**)obstack_finish(&cloud->obst);
910 DBG((env->dbg, LEVEL_3, "mst:\n"));
911 for (i = 0; i < cloud->n_memb; ++i) {
912 DEBUG_ONLY(co2_cloud_irn_t *ci = cloud->seq[i];)
913 DBG((env->dbg, LEVEL_3, "\t%+F -> %+F\n", ci->inh.irn, ci->mst_parent->inh.irn));
916 for (i = 0; i < cloud->n_memb; ++i) {
917 co2_cloud_irn_t *ci = cloud->seq[i];
918 int n_childs = ci->mst_n_childs;
921 ci->col_costs = OALLOCNZ(&cloud->obst, int, n_regs);
922 ci->tmp_coloring = OALLOCNZ(&cloud->obst, col_cost_pair_t, n_regs);
923 ci->fronts = OALLOCNZ(&cloud->obst, int, n_regs * n_childs);
924 ci->color_badness = OALLOCNZ(&cloud->obst, int, n_regs);
926 for (j = 0; j < env->n_regs; j++)
927 ci->col_costs[j] = INT_MAX;
930 determine_color_badness(cloud->mst_root, 0);
931 best_col = coalesce_top_down(cloud->mst_root, -1, 0);
932 unfix_subtree(cloud->mst_root);
933 apply_coloring(cloud->mst_root, best_col, 0);
935 /* The coloring should represent the one with the best costs. */
936 //materialize_coloring(&changed);
937 DBG((env->dbg, LEVEL_2, "\tbest coloring for root %+F was %d costing %d\n",
938 cloud->mst_root->inh.irn, best_col, examine_subtree_coloring(cloud->mst_root, best_col)));
940 /* Fix all nodes in the cloud. */
941 for (i = 0; i < cloud->n_memb; ++i)
942 cloud->seq[i]->inh.fixed = 1;
944 /* Free all space used while optimizing this cloud. */
945 obstack_free(&cloud->obst, NULL);
948 static int cloud_costs(co2_cloud_t *cloud)
952 for (i = 0; i < cloud->n_memb; ++i) {
953 co2_irn_t *ci = (co2_irn_t *) cloud->seq[i];
954 col_t col = get_col(cloud->env, ci->irn);
955 co_gs_foreach_neighb(ci->aff, n) {
956 col_t n_col = get_col(cloud->env, n->irn);
957 costs += col != n_col ? n->costs : 0;
964 static void writeback_colors(co2_t *env)
968 for (irn = env->touched; irn; irn = irn->touched_next) {
969 const arch_register_t *reg = arch_register_for_index(env->co->cls, irn->orig_col);
970 arch_set_irn_register((ir_node*)irn->irn, reg);
974 static void process(co2_t *env)
976 co2_cloud_t **clouds;
984 co_gs_foreach_aff_node(env->co, a) {
985 co2_cloud_irn_t *ci = get_co2_cloud_irn(env, a->irn);
994 clouds = XMALLOCN(co2_cloud_t*, n_clouds);
995 list_for_each_entry(co2_cloud_t, pos, &env->cloud_head, list)
997 qsort(clouds, n_clouds, sizeof(clouds[0]), cmp_clouds_gt);
999 for (i = 0; i < n_clouds; ++i) {
1000 init_costs += cloud_costs(clouds[i]);
1002 /* Process the cloud. */
1003 process_cloud(clouds[i]);
1005 all_costs += clouds[i]->costs;
1006 final_costs += cloud_costs(clouds[i]);
1009 DB((env->dbg, LEVEL_1, "all costs: %d, init costs: %d, final costs: %d\n", all_costs, init_costs, final_costs));
1014 static int co_solve_heuristic_new(copy_opt_t *co)
1018 ir_nodemap_init(&env.map, co->irg);
1019 obstack_init(&env.obst);
1023 env.n_regs = co->cls->n_regs;
1024 env.allocatable_regs = bitset_alloca(co->cls->n_regs);
1025 be_put_allocatable_regs(co->irg, co->cls, env.allocatable_regs);
1026 FIRM_DBG_REGISTER(env.dbg, "firm.be.co2");
1027 INIT_LIST_HEAD(&env.cloud_head);
1031 writeback_colors(&env);
1032 obstack_free(&env.obst, NULL);
1033 ir_nodemap_destroy(&env.map);
1037 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_copyheur2)
1038 void be_init_copyheur2(void)
1040 lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
1041 lc_opt_entry_t *ra_grp = lc_opt_get_grp(be_grp, "ra");
1042 lc_opt_entry_t *chordal_grp = lc_opt_get_grp(ra_grp, "chordal");
1043 lc_opt_entry_t *co2_grp = lc_opt_get_grp(chordal_grp, "co2");
1045 static co_algo_info copyheur = {
1046 co_solve_heuristic_new, 0
1049 lc_opt_add_table(co2_grp, options);
1050 be_register_copyopt("heur2", ©heur);