Fixed warnings.
[libfirm] / ir / be / becopyheur2.c
1 /*
2  * Copyright (C) 1995-2011 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief       More experiments on coalescing.
23  * @author      Sebastian Hack
24  * @date        14.04.2006
25  */
26 #include "config.h"
27
28 #include "lc_opts.h"
29 #include "lc_opts_enum.h"
30
31 #include <stdlib.h>
32 #include <limits.h>
33
34 #include "list.h"
35 #include "pdeq.h"
36 #include "bitset.h"
37 #include "raw_bitset.h"
38
39 #include "debug.h"
40 #include "bitfiddle.h"
41
42 #include "irgraph_t.h"
43 #include "irnode_t.h"
44 #include "irprintf.h"
45 #include "util.h"
46 #include "irtools.h"
47 #include "irnodemap.h"
48
49 #include "bemodule.h"
50 #include "beabi.h"
51 #include "benode.h"
52 #include "becopyopt.h"
53 #include "becopyopt_t.h"
54 #include "bechordal_t.h"
55 #include "beirg.h"
56
57 #define DUMP_BEFORE 1
58 #define DUMP_AFTER  2
59 #define DUMP_CLOUD  4
60 #define DUMP_ALL    2 * DUMP_CLOUD - 1
61
62 static unsigned dump_flags      = 0;
63 static int      subtree_iter    = 4;
64 static int      max_depth       = 20;
65 static double   constr_factor   = 0.9;
66
67 static const lc_opt_enum_mask_items_t dump_items[] = {
68         { "before",  DUMP_BEFORE },
69         { "after",   DUMP_AFTER  },
70         { "cloud",   DUMP_CLOUD  },
71         { "all",     DUMP_ALL    },
72         { NULL,      0 }
73 };
74
75 static lc_opt_enum_mask_var_t dump_var = {
76         &dump_flags, dump_items
77 };
78
79 static const lc_opt_table_entry_t options[] = {
80         LC_OPT_ENT_ENUM_MASK("dump", "dump ifg cloud",                                         &dump_var),
81         LC_OPT_ENT_INT      ("iter", "iterations for subtree nodes",                           &subtree_iter),
82         LC_OPT_ENT_DBL      ("cf",   "factor of constraint importance (between 0.0 and 1.0)",  &constr_factor),
83         LC_OPT_ENT_INT      ("max",  "maximum recursion depth",                                &max_depth),
84         LC_OPT_LAST
85 };
86
87 /*
88   ____  _             _
89  / ___|| |_ __ _ _ __| |_
90  \___ \| __/ _` | '__| __|
91   ___) | || (_| | |  | |_
92  |____/ \__\__,_|_|   \__|
93
94 */
95
96 #define INFEASIBLE(cost) ((cost) == INT_MAX)
97
98 typedef unsigned col_t;
99
100 typedef struct co2_irn_t       co2_irn_t;
101 typedef struct co2_cloud_t     co2_cloud_t;
102 typedef struct co2_cloud_irn_t co2_cloud_irn_t;
103
104 typedef struct {
105         col_t col;
106         int costs;
107 } col_cost_pair_t;
108
109 typedef struct {
110         ir_nodemap     map;
111         struct obstack obst;
112         copy_opt_t *co;
113         bitset_t   *allocatable_regs;
114         co2_irn_t  *touched;
115         int         visited;
116         int         n_regs;
117         struct list_head cloud_head;
118         DEBUG_ONLY(firm_dbg_module_t *dbg;)
119 } co2_t;
120
121 struct co2_irn_t {
122         const ir_node   *irn;
123         affinity_node_t *aff;
124         co2_irn_t       *touched_next;
125         col_t            tmp_col;
126         col_t            orig_col;
127         int              last_color_change;
128         bitset_t        *adm_cache;
129         unsigned         fixed          : 1;
130         unsigned         tmp_fixed      : 1;
131         unsigned         is_constrained : 1;
132         struct list_head changed_list;
133 };
134
135 struct co2_cloud_irn_t {
136         struct co2_irn_t   inh;
137         co2_cloud_t       *cloud;
138         int                visited;
139         int                index;
140         co2_cloud_irn_t   *mst_parent;
141         int                mst_costs;
142         int                mst_n_childs;
143         co2_cloud_irn_t  **mst_childs;
144         int               *col_costs;
145         int                costs;
146         int               *fronts;
147         int               *color_badness;
148         col_cost_pair_t   *tmp_coloring;
149         struct list_head   cloud_list;
150         struct list_head   mst_list;
151 };
152
153 struct co2_cloud_t {
154         co2_t            *env;
155         struct obstack    obst;
156         int               costs;
157         int               mst_costs;
158         int               inevit;
159         int               best_costs;
160         int               n_memb;
161         int               n_constr;
162         int               max_degree;
163         int               ticks;
164         double            freedom;
165         co2_cloud_irn_t  *master;
166         co2_cloud_irn_t  *mst_root;
167         co2_cloud_irn_t **seq;
168         struct list_head  members_head;
169         struct list_head  list;
170 };
171
172 typedef struct {
173         co2_cloud_irn_t *src, *tgt;
174         int costs;
175 } edge_t;
176
177 #define FRONT_BASE(ci,col)  ((ci)->fronts + col * (ci)->mst_n_childs)
178
179 static co2_irn_t *get_co2_irn(co2_t *env, const ir_node *node)
180 {
181         co2_irn_t *ci = ir_nodemap_get(co2_irn_t, &env->map, node);
182         if (ci == NULL) {
183                 ci = OALLOCZ(&env->obst, co2_irn_t);
184
185                 INIT_LIST_HEAD(&ci->changed_list);
186                 ci->touched_next = env->touched;
187                 ci->orig_col     = get_irn_col(node);
188                 env->touched     = ci;
189                 ci->irn          = node;
190                 ci->aff          = NULL;
191
192                 ir_nodemap_insert(&env->map, node, ci);
193         }
194         return ci;
195 }
196
197 static co2_cloud_irn_t *get_co2_cloud_irn(co2_t *env, const ir_node *node)
198 {
199         co2_cloud_irn_t *ci = ir_nodemap_get(co2_cloud_irn_t, &env->map, node);
200         if (ci == NULL) {
201                 ci = OALLOCZ(&env->obst, co2_cloud_irn_t);
202
203                 INIT_LIST_HEAD(&ci->inh.changed_list);
204                 ci->inh.touched_next = env->touched;
205                 ci->inh.orig_col     = get_irn_col(node);
206                 env->touched         = &ci->inh;
207                 ci->inh.irn          = node;
208                 ci->inh.aff          = get_affinity_info(env->co, node);
209
210                 INIT_LIST_HEAD(&ci->cloud_list);
211                 ci->mst_parent = ci;
212
213                 ir_nodemap_insert(&env->map, node, ci);
214         }
215         return ci;
216 }
217
218 #define CLOUD_WEIGHT(c) ((1 - constr_factor) * (c)->costs + constr_factor * (c)->freedom)
219
220 static int cmp_clouds_gt(const void *a, const void *b)
221 {
222         const co2_cloud_t * const *p = (const co2_cloud_t*const*)a;
223         const co2_cloud_t * const *q = (const co2_cloud_t*const*)b;
224         double c = CLOUD_WEIGHT(*p);
225         double d = CLOUD_WEIGHT(*q);
226         return QSORT_CMP(d, c);
227 }
228
229 /**
230  * An order on color/costs pairs.
231  * If the costs are equal, we use the color as a kind of normalization.
232  */
233 static int col_cost_pair_lt(const void *a, const void *b)
234 {
235         const col_cost_pair_t *p = (const col_cost_pair_t*)a;
236         const col_cost_pair_t *q = (const col_cost_pair_t*)b;
237         int c = p->costs;
238         int d = q->costs;
239         return QSORT_CMP(c, d);
240 }
241
242 static int cmp_edges(const void *a, const void *b)
243 {
244         const edge_t *p = (const edge_t*)a;
245         const edge_t *q = (const edge_t*)b;
246         return QSORT_CMP(q->costs, p->costs);
247 }
248
249 static col_t get_col(co2_t *env, const ir_node *irn)
250 {
251         co2_irn_t *ci = get_co2_irn(env, irn);
252         return ci->tmp_fixed ? ci->tmp_col : ci->orig_col;
253 }
254
255 static inline int color_is_fix(co2_t *env, const ir_node *irn)
256 {
257         co2_irn_t *ci = get_co2_irn(env, irn);
258         return ci->fixed || ci->tmp_fixed;
259 }
260
261 static inline bitset_t *get_adm(co2_t *env, co2_irn_t *ci)
262 {
263         if (ci->adm_cache == NULL) {
264                 const arch_register_req_t *req;
265                 ci->adm_cache = bitset_obstack_alloc(&env->obst, env->n_regs);
266                 req = arch_get_irn_register_req(ci->irn);
267
268                 if (arch_register_req_is(req, limited)) {
269                         int i, n;
270
271                         n = env->n_regs;
272                         for (i = 0; i < n; ++i) {
273                                 if (rbitset_is_set(req->limited, i))
274                                         bitset_set(ci->adm_cache, i);
275                         }
276                         ci->is_constrained = 1;
277                 } else {
278                         bitset_copy(ci->adm_cache, env->allocatable_regs);
279                 }
280         }
281
282         return ci->adm_cache;
283 }
284
285 static inline bitset_t *admissible_colors(co2_t *env, co2_irn_t *ci, bitset_t *bs)
286 {
287         bitset_copy(bs, get_adm(env, ci));
288         return bs;
289 }
290
291 static inline int is_color_admissible(co2_t *env, co2_irn_t *ci, col_t col)
292 {
293         bitset_t *bs = get_adm(env, ci);
294         return bitset_is_set(bs, col);
295 }
296
297 static inline int is_constrained(co2_t *env, co2_irn_t *ci)
298 {
299         if (!ci->adm_cache)
300                 get_adm(env, ci);
301         return ci->is_constrained;
302 }
303
304 static void incur_constraint_costs(co2_t *env, const ir_node *irn, col_cost_pair_t *col_costs, int costs)
305 {
306         const arch_register_req_t *req = arch_get_irn_register_req(irn);
307
308         if (arch_register_req_is(req, limited)) {
309                 unsigned n_regs   = env->co->cls->n_regs;
310                 unsigned n_constr = 0;
311                 unsigned i;
312
313                 n_constr = rbitset_popcount(req->limited, n_regs);
314                 for (i = 0; i < n_regs; ++i) {
315                         if (rbitset_is_set(req->limited, i)) {
316                                 col_costs[i].costs = add_saturated(col_costs[i].costs, costs / n_constr);
317                         }
318                 }
319         }
320 }
321
322 /**
323  * Determine costs which shall indicate how cheap/expensive it is to try
324  * to assign a node some color.
325  * The costs are computed for all colors. INT_MAX means that it is impossible
326  * to give the node that specific color.
327  *
328  * @param env       The co2 this pointer.
329  * @param irn       The node.
330  * @param col_costs An array of colors x costs where the costs are written to.
331  */
332 static void determine_color_costs(co2_t *env, co2_irn_t *ci, col_cost_pair_t *col_costs)
333 {
334         const ir_node *irn = ci->irn;
335         be_ifg_t *ifg      = env->co->cenv->ifg;
336         int n_regs         = env->co->cls->n_regs;
337         bitset_t *forb     = bitset_alloca(n_regs);
338         affinity_node_t *a = ci->aff;
339
340         const ir_node *pos;
341         neighbours_iter_t it;
342         int i;
343
344         /* Put all forbidden colors into the aux bitset. */
345         admissible_colors(env, ci, forb);
346         bitset_flip_all(forb);
347
348         for (i = 0; i < n_regs; ++i) {
349                 col_costs[i].col   = i;
350                 col_costs[i].costs = 0;
351         }
352
353         if (a) {
354                 co_gs_foreach_neighb(a, n) {
355                         if (color_is_fix(env, n->irn)) {
356                                 col_t col = get_col(env, n->irn);
357                                 col_costs[col].costs = add_saturated(col_costs[col].costs, -n->costs * 128);
358                         }
359
360                         incur_constraint_costs(env, n->irn, col_costs, -n->costs);
361                 }
362         }
363
364         be_ifg_foreach_neighbour(ifg, &it, irn, pos) {
365                 col_t col = get_col(env, pos);
366                 if (color_is_fix(env, pos)) {
367                         col_costs[col].costs  = INT_MAX;
368                 }
369                 else {
370                         incur_constraint_costs(env, pos, col_costs, INT_MAX);
371                         col_costs[col].costs = add_saturated(col_costs[col].costs, 8 * be_ifg_degree(ifg, pos));
372                 }
373         }
374         be_ifg_neighbours_break(&it);
375
376         /* Set the costs to infinity for each color which is not allowed at this node. */
377         bitset_foreach(forb, elm) {
378                 col_costs[elm].costs  = INT_MAX;
379         }
380
381 }
382
383 static void single_color_cost(co2_t *env, co2_irn_t *ci, col_t col, col_cost_pair_t *seq)
384 {
385         int n_regs = env->co->cls->n_regs;
386         int i;
387
388         for (i = 0; i < n_regs; ++i) {
389                 seq[i].col   = i;
390                 seq[i].costs = INT_MAX;
391         }
392
393         (void) ci;
394         assert(is_color_admissible(env, ci, col));
395         seq[col].col = 0;
396         seq[0].col   = col;
397         seq[0].costs = 0;
398 }
399
400 static void reject_coloring(struct list_head *h)
401 {
402         co2_irn_t *pos;
403
404         list_for_each_entry(co2_irn_t, pos, h, changed_list)
405                 pos->tmp_fixed = 0;
406 }
407
408 static void materialize_coloring(struct list_head *h)
409 {
410         co2_irn_t *pos;
411
412         list_for_each_entry(co2_irn_t, pos, h, changed_list) {
413                 pos->orig_col  = pos->tmp_col;
414                 pos->tmp_fixed = 0;
415         }
416 }
417
418 static int change_color_not(co2_t *env, const ir_node *irn, col_t not_col, struct list_head *parent_changed, int depth);
419
420 static int recolor(co2_t *env, const ir_node *irn, col_cost_pair_t *col_list, struct list_head *parent_changed, int depth)
421 {
422         int n_regs         = env->co->cls->n_regs;
423         be_ifg_t *ifg      = env->co->cenv->ifg;
424         co2_irn_t *ci      = get_co2_irn(env, irn);
425         int res            = 0;
426
427         int i;
428
429         if (depth >= max_depth)
430           return 0;
431
432         for (i = 0; i < n_regs; ++i) {
433                 col_t tgt_col  = col_list[i].col;
434                 unsigned costs = col_list[i].costs;
435                 int neigh_ok   = 1;
436
437                 struct list_head changed;
438                 const ir_node *n;
439                 neighbours_iter_t it;
440
441                 DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}trying color %d(%d) on %+F\n", depth, tgt_col, costs, irn));
442
443                 /* If the costs for that color (and all successive) are infinite, bail out we won't make it anyway. */
444                 if (INFEASIBLE(costs)) {
445                         DB((env->dbg, LEVEL_4, "\t\t%2{firm:indent}color %d infeasible\n", depth, tgt_col));
446                         ci->tmp_fixed = 0;
447                         return 0;
448                 }
449
450                 /* Set the new color of the node and mark the node as temporarily fixed. */
451                 ci->tmp_col     = tgt_col;
452                 ci->tmp_fixed   = 1;
453
454                 /*
455                 If that color has costs > 0, there's at least one neighbor having that color,
456                 so we will try to change the neighbors' colors, too.
457                 */
458                 INIT_LIST_HEAD(&changed);
459                 list_add(&ci->changed_list, &changed);
460
461                 be_ifg_foreach_neighbour(ifg, &it, irn, n) {
462
463                         /* try to re-color the neighbor if it has the target color. */
464                         if (get_col(env, n) == tgt_col) {
465                                 struct list_head tmp;
466
467                                 /*
468                                 Try to change the color of the neighbor and record all nodes which
469                                 get changed in the tmp list. Add this list to the "changed" list for
470                                 that color. If we did not succeed to change the color of the neighbor,
471                                 we bail out and try the next color.
472                                 */
473                                 INIT_LIST_HEAD(&tmp);
474                                 neigh_ok = change_color_not(env, n, tgt_col, &tmp, depth + 1);
475                                 list_splice(&tmp, &changed);
476                                 if (!neigh_ok)
477                                         break;
478                         }
479                 }
480                 be_ifg_neighbours_break(&it);
481
482                 /*
483                 We managed to assign the target color to all neighbors, so from the perspective
484                 of the current node, every thing was ok and we can return safely.
485                 */
486                 if (neigh_ok) {
487                         DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}color %d(%d) was ok\n", depth, tgt_col, costs));
488                         list_splice(&changed, parent_changed);
489                         res = 1;
490                         break;
491                 }
492
493                 /*
494                 If not, that color did not succeed and we unfix all nodes we touched
495                 by traversing the changed list and setting tmp_fixed to 0 for these nodes.
496                 */
497                 else
498                         reject_coloring(&changed);
499         }
500
501         return res;
502 }
503
504 static int change_color_not(co2_t *env, const ir_node *irn, col_t not_col, struct list_head *parent_changed, int depth)
505 {
506         co2_irn_t *ci = get_co2_irn(env, irn);
507         int res       = 0;
508         col_t col     = get_col(env, irn);
509
510         DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}clearing %+F(%d) of color %d\n", depth, irn, col, not_col));
511
512         /* the node does not have to forbidden color. That's fine, mark it as visited and return. */
513         if (col != not_col) {
514                 if (!ci->tmp_fixed) {
515                         ci->tmp_col     = col;
516                         ci->tmp_fixed   = 1;
517                 }
518
519                 list_add(&ci->changed_list, parent_changed);
520                 return 1;
521         }
522
523         /* The node has the color it should not have _and_ has not been visited yet. */
524         if (!color_is_fix(env, irn)) {
525                 int n_regs            = env->co->cls->n_regs;
526                 col_cost_pair_t *csts = ALLOCAN(col_cost_pair_t, n_regs);
527
528                 /* Get the costs for giving the node a specific color. */
529                 determine_color_costs(env, ci, csts);
530
531                 /* Since the node must not have the not_col, set the costs for that color to "infinity" */
532                 csts[not_col].costs = INT_MAX;
533
534                 /* sort the colors according costs, cheapest first. */
535                 qsort(csts, n_regs, sizeof(csts[0]), col_cost_pair_lt);
536
537                 /* Try recoloring the node using the color list. */
538                 res = recolor(env, irn, csts, parent_changed, depth);
539         }
540
541         /* If we came here, everything went ok. */
542         return res;
543 }
544
545 static int change_color_single(co2_t *env, const ir_node *irn, col_t tgt_col, struct list_head *parent_changed, int depth)
546 {
547         co2_irn_t *ci = get_co2_irn(env, irn);
548         col_t col     = get_col(env, irn);
549         int res       = 0;
550
551         DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}trying to set %+F(%d) to color %d\n", depth, irn, col, tgt_col));
552
553         /* the node has the wanted color. That's fine, mark it as visited and return. */
554         if (col == tgt_col) {
555                 if (!ci->tmp_fixed) {
556                         ci->tmp_col     = col;
557                         ci->tmp_fixed   = 1;
558                         list_add(&ci->changed_list, parent_changed);
559                 }
560
561                 res = 1;
562                 goto end;
563         }
564
565         if (!color_is_fix(env, irn) && is_color_admissible(env, ci, tgt_col)) {
566                 int n_regs           = env->co->cls->n_regs;
567                 col_cost_pair_t *seq = ALLOCAN(col_cost_pair_t, n_regs);
568
569                 /* Get the costs for giving the node a specific color. */
570                 single_color_cost(env, ci, tgt_col, seq);
571
572                 /* Try recoloring the node using the color list. */
573                 res = recolor(env, irn, seq, parent_changed, depth);
574
575         }
576
577 end:
578         DB((env->dbg, LEVEL_3, "\t\t%2{firm:indent}color %d %s for %+F\n", depth, tgt_col, res ? "was ok" : "failed", irn));
579         return res;
580 }
581
582 /**
583  * Examine the costs of the current coloring concerning a MST subtree.
584  * @param ci  The subtree root.
585  * @param col The color of @p ci.
586  * @return    The best coloring for that subtree under the assumption that @p ci has color @p col.
587  */
588 static int examine_subtree_coloring(co2_cloud_irn_t *ci, col_t col)
589 {
590         int *front = FRONT_BASE(ci, col);
591         int cost   = 0;
592         int i;
593
594         for (i = 0; i < ci->mst_n_childs; ++i) {
595                 co2_cloud_irn_t *chld = ci->mst_childs[i];
596                 col_t chld_col        = front[i];
597
598                 cost += examine_subtree_coloring(chld, chld_col);
599                 cost += col != chld_col ? chld->mst_costs : 0;
600         }
601
602         return cost;
603 }
604
605 /**
606  * Determine color badnesses of a node.
607  * Badness means that it is unlikely that the node in question can
608  * obtain a color. The higher the badness, the more unlikely it is that
609  * the node can be assigned that color.
610  * @param ci      The node.
611  * @param badness An integer array as long as there are registers.
612  * @note          The array <code>badness</code> is not cleared.
613  */
614 static void node_color_badness(co2_cloud_irn_t *ci, int *badness)
615 {
616         co2_t *env     = ci->cloud->env;
617         co2_irn_t *ir  = &ci->inh;
618         int n_regs     = env->n_regs;
619         be_ifg_t *ifg  = env->co->cenv->ifg;
620         bitset_t *bs   = bitset_alloca(n_regs);
621
622         const ir_node *irn;
623         neighbours_iter_t it;
624
625         admissible_colors(env, &ci->inh, bs);
626         bitset_flip_all(bs);
627         bitset_foreach(bs, elm)
628                 badness[elm] = ci->costs;
629
630         /* Use constrained/fixed interfering neighbors to influence the color badness */
631         be_ifg_foreach_neighbour(ifg, &it, ir->irn, irn) {
632                 co2_irn_t *ni = get_co2_irn(env, irn);
633
634                 admissible_colors(env, ni, bs);
635                 if (bitset_popcount(bs) == 1) {
636                         size_t c = bitset_next_set(bs, 0);
637                         badness[c] += ci->costs;
638                 }
639
640                 else if (ni->fixed) {
641                         col_t c = get_col(env, ni->irn);
642                         badness[c] += ci->costs;
643                 }
644         }
645         be_ifg_neighbours_break(&it);
646 }
647
648 /**
649  * Determine the badness of a MST subtree.
650  * The badness is written into the <code>color_badness</code> array of each node and accumulated in the parents.
651  * @see node_color_badness() for a definition of badness.
652  * @param ci    The root of the subtree.
653  * @param depth Depth for debugging purposes.
654  */
655 static void determine_color_badness(co2_cloud_irn_t *ci, int depth)
656 {
657         co2_t *env     = ci->cloud->env;
658         int i, j;
659
660         node_color_badness(ci, ci->color_badness);
661
662         /* Collect the color badness for the whole subtree */
663         for (i = 0; i < ci->mst_n_childs; ++i) {
664                 co2_cloud_irn_t *child = ci->mst_childs[i];
665                 determine_color_badness(child, depth + 1);
666
667                 for (j = 0; j < env->n_regs; ++j)
668                         ci->color_badness[j] += child->color_badness[j];
669         }
670
671         for (j = 0; j < env->n_regs; ++j)
672                 DBG((env->dbg, LEVEL_2, "%2{firm:indent}%+F col %d badness %d\n", depth, ci->inh.irn, j, ci->color_badness[j]));
673 }
674
675 /**
676  * Unfix all nodes in a MST subtree.
677  */
678 static void unfix_subtree(co2_cloud_irn_t *ci)
679 {
680         int i;
681
682         ci->inh.fixed = 0;
683         for (i = 0; i < ci->mst_n_childs; ++i)
684                 unfix_subtree(ci->mst_childs[i]);
685 }
686
687 static int coalesce_top_down(co2_cloud_irn_t *ci, int child_nr, int depth)
688 {
689         co2_t *env           = ci->cloud->env;
690         col_cost_pair_t *seq = ALLOCAN(col_cost_pair_t, env->n_regs);
691         int is_root          = ci->mst_parent == ci;
692         col_t parent_col     = is_root ? (col_t) -1 : get_col(env, ci->mst_parent->inh.irn);
693         int min_badness      = INT_MAX;
694         int best_col_costs   = INT_MAX;
695         int best_col         = -1;
696         int n_regs           = env->n_regs;
697         int n_iter           = is_root ? MIN(n_regs, subtree_iter) : 1;
698
699         struct list_head changed;
700         int ok, i, j;
701
702         for (i = 0; i < n_regs; ++i) {
703                 int badness = ci->color_badness[i];
704
705                 seq[i].col   = i;
706                 seq[i].costs = is_color_admissible(env, &ci->inh, i) ? badness : INT_MAX;
707
708                 min_badness = MIN(min_badness, badness);
709         }
710
711         /* If we are not the root and the parent's color is allowed for this node give it top prio. */
712         if (!is_root && is_color_admissible(env, &ci->inh, parent_col))
713                 seq[parent_col].costs = min_badness - 1;
714
715         /* Sort the colors. The will be processed in that ordering. */
716         qsort(seq, env->n_regs, sizeof(seq[0]), col_cost_pair_lt);
717
718         DBG((env->dbg, LEVEL_2, "\t%2{firm:indent}starting top-down coalesce for %+F\n", depth, ci->inh.irn));
719         INIT_LIST_HEAD(&changed);
720         for (i = 0; i < (best_col < 0 ? n_regs : n_iter); ++i) {
721                 col_t col    = seq[i].col;
722                 int add_cost = !is_root && col != parent_col ? ci->mst_costs : 0;
723
724                 int subtree_costs, sum_costs;
725
726                 DBG((env->dbg, LEVEL_2, "\t%2{firm:indent}%+F trying color %d\n", depth, ci->inh.irn, col));
727
728                 unfix_subtree(ci);
729                 INIT_LIST_HEAD(&changed);
730                 ok = change_color_single(env, ci->inh.irn, col, &changed, depth);
731                 if (ok) {
732                         materialize_coloring(&changed);
733                         ci->inh.fixed = 1;
734                 }
735
736                 else
737                         continue;
738
739                 for (j = 0; j < ci->mst_n_childs; ++j) {
740                         co2_cloud_irn_t *child = ci->mst_childs[j];
741                         ok = coalesce_top_down(child, j, depth + 1) >= 0;
742                         if (ok)
743                                 child->inh.fixed = 1;
744                         else
745                                 break;
746                 }
747
748                 /* If the subtree could not be colored, we have to try another color. */
749                 if (!ok)
750                         continue;
751
752                 subtree_costs      = examine_subtree_coloring(ci, col);
753                 sum_costs          = subtree_costs + add_cost;
754                 DBG((env->dbg, LEVEL_2, "\t%2{firm:indent}-> %+F costing %d + %d is ok.\n", depth, ci->inh.irn, subtree_costs, add_cost));
755
756                 if (sum_costs < best_col_costs) {
757                         best_col           = col;
758                         best_col_costs     = sum_costs;
759                         ci->col_costs[col] = subtree_costs;
760                 }
761
762                 if (sum_costs == 0)
763                         break;
764         }
765
766         if (!is_root) {
767                 int *front = FRONT_BASE(ci->mst_parent, parent_col);
768                 front[child_nr] = best_col;
769         }
770
771         return best_col;
772 }
773
774 static void populate_cloud(co2_t *env, co2_cloud_t *cloud, affinity_node_t *a, int curr_costs)
775 {
776         be_ifg_t *ifg       = env->co->cenv->ifg;
777         co2_cloud_irn_t *ci = get_co2_cloud_irn(env, a->irn);
778         int costs           = 0;
779
780         if (ci->cloud)
781                 return;
782
783         /* mark the node as visited and add it to the cloud. */
784         ci->cloud   = cloud;
785         list_add(&ci->cloud_list, &cloud->members_head);
786
787         DB((env->dbg, LEVEL_2, "\t%+F\n", ci->inh.irn));
788
789         /* determine the nodes costs */
790         co_gs_foreach_neighb(a, n) {
791                 costs += n->costs;
792                 DB((env->dbg, LEVEL_3, "\t\tneigh %+F cost %d\n", n->irn, n->costs));
793                 if (be_ifg_connected(ifg, a->irn, n->irn))
794                         cloud->inevit += n->costs;
795         }
796
797         /* add the node's cost to the total costs of the cloud. */
798         ci->costs          = costs;
799         cloud->costs      += costs;
800         cloud->n_constr   += is_constrained(env, &ci->inh);
801         cloud->freedom    += bitset_popcount(get_adm(env, &ci->inh));
802         cloud->max_degree  = MAX(cloud->max_degree, ci->inh.aff->degree);
803         cloud->n_memb++;
804
805         /* If this is the heaviest node in the cloud, set it as the cloud's master. */
806         if (costs >= curr_costs) {
807                 curr_costs    = costs;
808                 cloud->master = ci;
809         }
810
811         /* add all the neighbors of the node to the cloud. */
812         co_gs_foreach_neighb(a, n) {
813                 affinity_node_t *an = get_affinity_info(env->co, n->irn);
814                 assert(an);
815                 populate_cloud(env, cloud, an, curr_costs);
816         }
817 }
818
819 static co2_cloud_t *new_cloud(co2_t *env, affinity_node_t *a)
820 {
821         co2_cloud_t *cloud = OALLOC(&env->obst, co2_cloud_t);
822         co2_cloud_irn_t *ci;
823         int i;
824
825         DBG((env->dbg, LEVEL_2, "new cloud with %+F\n", a->irn));
826         memset(cloud, 0, sizeof(cloud[0]));
827         INIT_LIST_HEAD(&cloud->members_head);
828         INIT_LIST_HEAD(&cloud->list);
829         list_add(&cloud->list, &env->cloud_head);
830         cloud->best_costs = INT_MAX;
831         cloud->env = env;
832         env->visited++;
833         populate_cloud(env, cloud, a, 0);
834         cloud->freedom = (cloud->n_memb * env->n_regs) / cloud->freedom;
835
836         /* Also allocate space for the node sequence and compute that sequence. */
837         cloud->seq = OALLOCN(&env->obst, co2_cloud_irn_t*, cloud->n_memb);
838
839         i = 0;
840         list_for_each_entry(co2_cloud_irn_t, ci, &cloud->members_head, cloud_list) {
841                 ci->index       = i;
842                 cloud->seq[i++] = ci;
843         }
844         DBG((env->dbg, LEVEL_2, "cloud cost %d, freedom %f\n", cloud->costs, cloud->freedom));
845
846         return cloud;
847 }
848
849 static void apply_coloring(co2_cloud_irn_t *ci, col_t col, int depth)
850 {
851         const ir_node *irn = ci->inh.irn;
852         int *front   = FRONT_BASE(ci, col);
853         int i;
854         struct list_head changed;
855
856         INIT_LIST_HEAD(&changed);
857
858         DBG((ci->cloud->env->dbg, LEVEL_2, "%2{firm:indent}setting %+F to %d\n", depth, irn, col));
859         change_color_single(ci->cloud->env, irn, col, &changed, depth);
860         materialize_coloring(&changed);
861
862         for (i = 0; i < ci->mst_n_childs; ++i) {
863                 apply_coloring(ci->mst_childs[i], front[i], depth + 1);
864         }
865 }
866
867 static co2_cloud_irn_t *find_mst_root(co2_cloud_irn_t *ci)
868 {
869         while (ci != ci->mst_parent)
870                 ci = ci->mst_parent;
871         return ci;
872 }
873
874
875 static void process_cloud(co2_cloud_t *cloud)
876 {
877         co2_t *env  = cloud->env;
878         int n_regs  = env->n_regs;
879         int n_edges = 0;
880         int *mst_edges = XMALLOCNZ(int, cloud->n_memb * cloud->n_memb);
881         pdeq *q;
882
883         edge_t *edges;
884         int i;
885         int best_col;
886
887         /* Collect all edges in the cloud on an obstack and sort the increasingly */
888         obstack_init(&cloud->obst);
889         for (i = 0; i < cloud->n_memb; ++i) {
890                 co2_cloud_irn_t *ci = cloud->seq[i];
891
892                 co_gs_foreach_neighb(ci->inh.aff, n) {
893                         co2_cloud_irn_t *ni = get_co2_cloud_irn(cloud->env, n->irn);
894                         if (ci->index < ni->index) {
895                                 edge_t e;
896                                 e.src   = ci;
897                                 e.tgt   = ni;
898                                 e.costs = n->costs;
899                                 obstack_grow(&cloud->obst, &e, sizeof(e));
900                                 n_edges++;
901                         }
902                 }
903         }
904         edges = (edge_t*)obstack_finish(&cloud->obst);
905         qsort(edges, n_edges, sizeof(edges[0]), cmp_edges);
906
907         /* Compute the maximum spanning tree using Kruskal/Union-Find */
908         DBG((env->dbg, LEVEL_2, "computing spanning tree of cloud with master %+F\n", cloud->master->inh.irn));
909         for (i = 0; i < n_edges; ++i) {
910                 edge_t *e        = &edges[i];
911                 co2_cloud_irn_t *rs = find_mst_root(e->src);
912                 co2_cloud_irn_t *rt = find_mst_root(e->tgt);
913
914                 /* if the union/find roots are different */
915                 if (rs != rt) {
916                         int si = e->src->index;
917                         int ti = e->tgt->index;
918
919                         /* unify the sets */
920                         rs->mst_parent = rt;
921                         DBG((env->dbg, LEVEL_2, "\tadding edge %+F -- %+F cost %d\n", rs->inh.irn, rt->inh.irn, e->costs));
922
923                         /* this edge is in the MST, so set it in the bitset. */
924                         mst_edges[si * cloud->n_memb + ti] = e->costs;
925                         mst_edges[ti * cloud->n_memb + si] = e->costs;
926                 }
927         }
928         obstack_free(&cloud->obst, edges);
929
930         cloud->master->mst_parent = cloud->master;
931         cloud->mst_root = cloud->master;
932         q = new_pdeq1(cloud->master);
933         while (!pdeq_empty(q)) {
934                 co2_cloud_irn_t *ci = (co2_cloud_irn_t*)pdeq_getl(q);
935                 int ofs    = ci->index * cloud->n_memb;
936                 int end    = ofs + cloud->n_memb;
937                 int i;
938
939                 ci->mst_n_childs = 0;
940                 for (i = ofs; i < end; ++i) {
941                         if (mst_edges[i] != 0) {
942                                 int other = i - ofs;
943                                 co2_cloud_irn_t *child = cloud->seq[i - ofs];
944
945                                 /* put the child to the worklist */
946                                 pdeq_putr(q, child);
947
948                                 /* make ci the parent of the child and add the child to the children array of the parent */
949                                 child->mst_parent = ci;
950                                 child->mst_costs  = mst_edges[i];
951                                 ci->mst_n_childs++;
952                                 obstack_ptr_grow(&cloud->obst, child);
953
954                                 mst_edges[other * cloud->n_memb + ci->index] = 0;
955                                 mst_edges[i] = 0;
956                         }
957                 }
958
959                 obstack_ptr_grow(&cloud->obst, NULL);
960                 ci->mst_childs = (co2_cloud_irn_t**)obstack_finish(&cloud->obst);
961         }
962         del_pdeq(q);
963         free(mst_edges);
964
965
966         DBG((env->dbg, LEVEL_3, "mst:\n"));
967         for (i = 0; i < cloud->n_memb; ++i) {
968                 DEBUG_ONLY(co2_cloud_irn_t *ci = cloud->seq[i];)
969                 DBG((env->dbg, LEVEL_3, "\t%+F -> %+F\n", ci->inh.irn, ci->mst_parent->inh.irn));
970         }
971
972         for (i = 0; i < cloud->n_memb; ++i) {
973                 co2_cloud_irn_t *ci = cloud->seq[i];
974                 int n_childs = ci->mst_n_childs;
975                 int j;
976
977                 ci->col_costs       = OALLOCNZ(&cloud->obst, int,             n_regs);
978                 ci->tmp_coloring    = OALLOCNZ(&cloud->obst, col_cost_pair_t, n_regs);
979                 ci->fronts          = OALLOCNZ(&cloud->obst, int,             n_regs * n_childs);
980                 ci->color_badness   = OALLOCNZ(&cloud->obst, int,             n_regs);
981
982                 for (j = 0; j < env->n_regs; j++)
983                         ci->col_costs[j] = INT_MAX;
984         }
985
986         determine_color_badness(cloud->mst_root, 0);
987         best_col = coalesce_top_down(cloud->mst_root, -1, 0);
988         unfix_subtree(cloud->mst_root);
989         apply_coloring(cloud->mst_root, best_col, 0);
990
991         /* The coloring should represent the one with the best costs. */
992         //materialize_coloring(&changed);
993         DBG((env->dbg, LEVEL_2, "\tbest coloring for root %+F was %d costing %d\n",
994                 cloud->mst_root->inh.irn, best_col, examine_subtree_coloring(cloud->mst_root, best_col)));
995
996         /* Fix all nodes in the cloud. */
997         for (i = 0; i < cloud->n_memb; ++i)
998                 cloud->seq[i]->inh.fixed = 1;
999
1000         /* Free all space used while optimizing this cloud. */
1001         obstack_free(&cloud->obst, NULL);
1002 }
1003
1004 static int cloud_costs(co2_cloud_t *cloud)
1005 {
1006         int i, costs = 0;
1007
1008         for (i = 0; i < cloud->n_memb; ++i) {
1009                 co2_irn_t *ci = (co2_irn_t *) cloud->seq[i];
1010                 col_t col = get_col(cloud->env, ci->irn);
1011                 co_gs_foreach_neighb(ci->aff, n) {
1012                         col_t n_col = get_col(cloud->env, n->irn);
1013                         costs += col != n_col ? n->costs : 0;
1014                 }
1015         }
1016
1017         return costs / 2;
1018 }
1019
1020 static void writeback_colors(co2_t *env)
1021 {
1022         co2_irn_t *irn;
1023
1024         for (irn = env->touched; irn; irn = irn->touched_next) {
1025                 const arch_register_t *reg = arch_register_for_index(env->co->cls, irn->orig_col);
1026                 arch_set_irn_register((ir_node*)irn->irn, reg);
1027         }
1028 }
1029
1030 static void process(co2_t *env)
1031 {
1032         co2_cloud_t *pos;
1033         co2_cloud_t **clouds;
1034         int n_clouds;
1035         int i;
1036         int init_costs  = 0;
1037         int all_costs   = 0;
1038         int final_costs = 0;
1039
1040         n_clouds = 0;
1041         co_gs_foreach_aff_node(env->co, a) {
1042                 co2_cloud_irn_t *ci = get_co2_cloud_irn(env, a->irn);
1043
1044                 if (!ci->cloud) {
1045                         new_cloud(env, a);
1046                         n_clouds++;
1047                 }
1048         }
1049
1050         i = 0;
1051         clouds = XMALLOCN(co2_cloud_t*, n_clouds);
1052         list_for_each_entry(co2_cloud_t, pos, &env->cloud_head, list)
1053                 clouds[i++] = pos;
1054         qsort(clouds, n_clouds, sizeof(clouds[0]), cmp_clouds_gt);
1055
1056         for (i = 0; i < n_clouds; ++i) {
1057                 init_costs  += cloud_costs(clouds[i]);
1058
1059                 /* Process the cloud. */
1060                 process_cloud(clouds[i]);
1061
1062                 all_costs   += clouds[i]->costs;
1063                 final_costs += cloud_costs(clouds[i]);
1064         }
1065
1066         DB((env->dbg, LEVEL_1, "all costs: %d, init costs: %d, final costs: %d\n", all_costs, init_costs, final_costs));
1067
1068         xfree(clouds);
1069 }
1070
1071 static int co_solve_heuristic_new(copy_opt_t *co)
1072 {
1073         co2_t env;
1074
1075         ir_nodemap_init(&env.map, co->irg);
1076         obstack_init(&env.obst);
1077         env.touched     = NULL;
1078         env.visited     = 0;
1079         env.co          = co;
1080         env.n_regs      = co->cls->n_regs;
1081         env.allocatable_regs = bitset_alloca(co->cls->n_regs);
1082         be_put_allocatable_regs(co->cenv->irg, co->cls, env.allocatable_regs);
1083         FIRM_DBG_REGISTER(env.dbg, "firm.be.co2");
1084         INIT_LIST_HEAD(&env.cloud_head);
1085
1086         process(&env);
1087
1088         writeback_colors(&env);
1089         obstack_free(&env.obst, NULL);
1090         ir_nodemap_destroy(&env.map);
1091         return 0;
1092 }
1093
1094 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_copyheur2)
1095 void be_init_copyheur2(void)
1096 {
1097         lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
1098         lc_opt_entry_t *ra_grp = lc_opt_get_grp(be_grp, "ra");
1099         lc_opt_entry_t *chordal_grp = lc_opt_get_grp(ra_grp, "chordal");
1100         lc_opt_entry_t *co2_grp = lc_opt_get_grp(chordal_grp, "co2");
1101
1102         static co_algo_info copyheur = {
1103                 co_solve_heuristic_new, 0
1104         };
1105
1106         lc_opt_add_table(co2_grp, options);
1107         be_register_copyopt("heur2", &copyheur);
1108 }