dump: Remove extra leading dashes from dump suffixes.
[libfirm] / ir / be / bepbqpcoloring.c
1 /*
2  * Copyright (C) 1995-2008 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       PBQP based register allocation.
23  * @author      Thomas Bersch
24  * @date        27.11.2009
25  */
26
27 /* miscellaneous includes */
28 #include "config.h"
29
30 #include "debug.h"
31 #include "error.h"
32
33 #include "irdom.h"
34 #include "irdump.h"
35 #include "iredges_t.h"
36 #include "irprintf.h"
37 #include "irgwalk.h"
38 #include "irtools.h"
39 #include "time.h"
40 #include "execfreq_t.h"
41 #include "bipartite.h"
42
43 /* libfirm/ir/be includes */
44 #include "bearch.h"
45 #include "beirg.h"
46 #include "besched.h"
47 #include "bemodule.h"
48 #include "bechordal_common.h"
49 #include "bechordal.h"
50 #include "bechordal_t.h"
51 #include "beinsn_t.h"
52 #include "benode.h"
53 #include "belive.h"
54 #include "belive_t.h"
55 #include "beutil.h"
56 #include "plist.h"
57 #include "pqueue.h"
58 #include "becopyopt.h"
59
60 /* pbqp includes */
61 #include "kaps.h"
62 #include "matrix.h"
63 #include "vector.h"
64 #include "vector_t.h"
65 #include "heuristical_co.h"
66 #include "heuristical_co_ld.h"
67 #include "pbqp_t.h"
68 #include "html_dumper.h"
69 #include "pbqp_node_t.h"
70 #include "pbqp_node.h"
71 #include "pbqp_edge_t.h"
72
73 #define TIMER                 0
74 #define PRINT_RPEO            0
75 #define USE_BIPARTIT_MATCHING 0
76 #define DO_USEFUL_OPT         1
77
78
79 static int use_exec_freq     = true;
80 static int use_late_decision = false;
81
82 typedef struct be_pbqp_alloc_env_t {
83         pbqp_t                      *pbqp_inst;         /**< PBQP instance for register allocation */
84         ir_graph                    *irg;               /**< The graph under examination. */
85         const arch_register_class_t *cls;               /**< Current processed register class */
86         be_lv_t                     *lv;
87         bitset_t                    *allocatable_regs;
88         pbqp_matrix_t               *ife_matrix_template;
89         pbqp_matrix_t               *aff_matrix_template;
90         plist_t                     *rpeo;
91         unsigned                    *restr_nodes;
92         unsigned                    *ife_edge_num;
93         ir_execfreq_int_factors      execfreq_factors;
94         be_chordal_env_t            *env;
95 } be_pbqp_alloc_env_t;
96
97
98 #define is_Reg_Phi(irn)                                        (is_Phi(irn) && mode_is_data(get_irn_mode(irn)))
99 #define get_Perm_src(irn)                                      (get_irn_n(get_Proj_pred(irn), get_Proj_proj(irn)))
100 #define is_Perm_Proj(irn)                                      (is_Proj(irn) && be_is_Perm(get_Proj_pred(irn)))
101 #define insert_edge(pbqp, src_node, trg_node, template_matrix) (add_edge_costs(pbqp, get_irn_idx(src_node), get_irn_idx(trg_node), pbqp_matrix_copy(pbqp, template_matrix)))
102 #define get_free_regs(restr_nodes, cls, irn)                   (arch_register_class_n_regs(cls) - restr_nodes[get_irn_idx(irn)])
103
104 static const lc_opt_table_entry_t options[] = {
105         LC_OPT_ENT_BOOL("exec_freq", "use exec_freq",  &use_exec_freq),
106         LC_OPT_ENT_BOOL("late_decision", "use late decision for register allocation",  &use_late_decision),
107         LC_OPT_LAST
108 };
109
110 #if KAPS_DUMP
111 static FILE *my_open(const be_chordal_env_t *env, const char *prefix, const char *suffix)
112 {
113         FILE       *result;
114         char        buf[1024];
115         size_t      i;
116         size_t      n;
117         char       *tu_name;
118         const char *cup_name = be_get_irg_main_env(env->irg)->cup_name;
119
120         n = strlen(cup_name);
121         tu_name = XMALLOCN(char, n + 1);
122         strcpy(tu_name, cup_name);
123         for (i = 0; i < n; ++i)
124                 if (tu_name[i] == '.')
125                         tu_name[i] = '_';
126
127         ir_snprintf(buf, sizeof(buf), "%s%s_%F_%s%s", prefix, tu_name, env->irg, env->cls->name, suffix);
128         xfree(tu_name);
129         result = fopen(buf, "wt");
130         if (result == NULL) {
131                 panic("Couldn't open '%s' for writing.", buf);
132         }
133
134         return result;
135 }
136 #endif
137
138
139 static void create_pbqp_node(be_pbqp_alloc_env_t *pbqp_alloc_env, ir_node *irn)
140 {
141         const arch_register_class_t *cls = pbqp_alloc_env->cls;
142         pbqp_t   *pbqp_inst              = pbqp_alloc_env->pbqp_inst;
143         bitset_t *allocatable_regs       = pbqp_alloc_env->allocatable_regs;
144         unsigned  colors_n               = arch_register_class_n_regs(cls);
145         unsigned  cntConstrains          = 0;
146
147         /* create costs vector depending on register constrains */
148         vector_t *costs_vector = vector_alloc(pbqp_inst, colors_n);
149
150         /* set costs depending on register constrains */
151         unsigned idx;
152         for (idx = 0; idx < colors_n; idx++) {
153                 const arch_register_req_t *req = arch_get_irn_register_req(irn);
154                 const arch_register_t     *reg = arch_register_for_index(cls, idx);
155                 if (!bitset_is_set(allocatable_regs, idx)
156                     || !arch_reg_is_allocatable(req, reg)) {
157                         /* constrained */
158                         vector_set(costs_vector, idx, INF_COSTS);
159                         cntConstrains++;
160                 }
161         }
162
163         /* add vector to pbqp node */
164         add_node_costs(pbqp_inst, get_irn_idx(irn), costs_vector);
165         pbqp_alloc_env->restr_nodes[get_irn_idx(irn)] = cntConstrains;
166 }
167
168 static void insert_ife_edge(be_pbqp_alloc_env_t *pbqp_alloc_env, ir_node *src_node, ir_node *trg_node)
169 {
170         pbqp_t                      *pbqp                = pbqp_alloc_env->pbqp_inst;
171         const arch_register_class_t *cls                 = pbqp_alloc_env->cls;
172         pbqp_matrix_t               *ife_matrix_template = pbqp_alloc_env->ife_matrix_template;
173         unsigned                    *restr_nodes         = pbqp_alloc_env->restr_nodes;
174
175         if (get_edge(pbqp, get_irn_idx(src_node), get_irn_idx(trg_node)) == NULL) {
176
177                 /* increase ife edge counter */
178                 pbqp_alloc_env->ife_edge_num[get_irn_idx(src_node)]++;
179                 pbqp_alloc_env->ife_edge_num[get_irn_idx(trg_node)]++;
180
181 #if DO_USEFUL_OPT || USE_BIPARTIT_MATCHING
182                 /* do useful optimization to speed up pbqp solving (we can do this because we know our matrix) */
183                 if (get_free_regs(restr_nodes, cls, src_node) == 1 && get_free_regs(restr_nodes, cls, trg_node) == 1) {
184                         assert(vector_get_min_index(get_node(pbqp, get_irn_idx(src_node))->costs) !=
185                                vector_get_min_index(get_node(pbqp, get_irn_idx(trg_node))->costs) &&
186                                "Interfering nodes must not have the same register!");
187                         return;
188                 }
189                 if (get_free_regs(restr_nodes, cls, src_node) == 1 || get_free_regs(restr_nodes, cls, trg_node) == 1) {
190                         if (get_free_regs(restr_nodes, cls, src_node) == 1) {
191                                 unsigned idx = vector_get_min_index(get_node(pbqp, get_irn_idx(src_node))->costs);
192                                 vector_set(get_node(pbqp, get_irn_idx(trg_node))->costs, idx, INF_COSTS);
193                         }
194                         else {
195                                 unsigned idx = vector_get_min_index(get_node(pbqp, get_irn_idx(trg_node))->costs);
196                                 vector_set(get_node(pbqp, get_irn_idx(src_node))->costs, idx, INF_COSTS);
197                         }
198                         return;
199                 }
200 #endif
201                 /* insert interference edge */
202                 insert_edge(pbqp, src_node, trg_node, ife_matrix_template);
203         }
204 }
205
206 static void insert_afe_edge(be_pbqp_alloc_env_t *pbqp_alloc_env, ir_node *src_node, ir_node *trg_node, int pos)
207 {
208         pbqp_t                      *pbqp        = pbqp_alloc_env->pbqp_inst;
209         const arch_register_class_t *cls         = pbqp_alloc_env->cls;
210         unsigned                    *restr_nodes = pbqp_alloc_env->restr_nodes;
211         pbqp_matrix_t               *afe_matrix  = pbqp_matrix_alloc(pbqp, arch_register_class_n_regs(cls), arch_register_class_n_regs(cls));
212         unsigned                     colors_n    = arch_register_class_n_regs(cls);
213
214         if (get_edge(pbqp, get_irn_idx(src_node), get_irn_idx(trg_node)) == NULL) {
215                 if (use_exec_freq) {
216                         /* get exec_freq for copy_block */
217                         ir_node *root_bl = get_nodes_block(src_node);
218                         ir_node *copy_bl = is_Phi(src_node) ? get_Block_cfgpred_block(root_bl, pos) : root_bl;
219                         int      res     = get_block_execfreq_int(&pbqp_alloc_env->execfreq_factors, copy_bl);
220
221                         /* create afe-matrix */
222                         unsigned row, col;
223                         for (row = 0; row < colors_n; row++) {
224                                 for (col = 0; col < colors_n; col++) {
225                                         if (row != col)
226                                                 pbqp_matrix_set(afe_matrix, row, col, (num)res);
227                                 }
228                         }
229                 }
230                 else {
231                         afe_matrix = pbqp_alloc_env->aff_matrix_template;
232                 }
233 #if DO_USEFUL_OPT || USE_BIPARTIT_MATCHING
234                 /* do useful optimization to speed up pbqp solving */
235                 if (get_free_regs(restr_nodes, cls, src_node) == 1 && get_free_regs(restr_nodes, cls, trg_node) == 1) {
236                         return;
237                 }
238                 if (get_free_regs(restr_nodes, cls, src_node) == 1 || get_free_regs(restr_nodes, cls, trg_node) == 1) {
239                         if (get_free_regs(restr_nodes, cls, src_node) == 1) {
240                                 unsigned regIdx = vector_get_min_index(get_node(pbqp, get_irn_idx(src_node))->costs);
241                                 vector_add_matrix_col(get_node(pbqp, get_irn_idx(trg_node))->costs, afe_matrix, regIdx);
242                         }
243                         else {
244                                 unsigned regIdx = vector_get_min_index(get_node(pbqp, get_irn_idx(trg_node))->costs);
245                                 vector_add_matrix_col(get_node(pbqp, get_irn_idx(src_node))->costs, afe_matrix, regIdx);
246                         }
247                         return;
248                 }
249 #endif
250                 /* insert interference edge */
251                 insert_edge(pbqp, src_node, trg_node, afe_matrix);
252         }
253 }
254
255 static void create_affinity_edges(ir_node *irn, void *env)
256 {
257         be_pbqp_alloc_env_t         *pbqp_alloc_env = (be_pbqp_alloc_env_t*)env;
258         const arch_register_class_t *cls            = pbqp_alloc_env->cls;
259         const arch_register_req_t   *req            = arch_get_irn_register_req(irn);
260         unsigned                     pos;
261         unsigned                     max;
262
263         if (is_Reg_Phi(irn)) { /* Phis */
264                 for (pos = 0, max = get_irn_arity(irn); pos < max; ++pos) {
265                         ir_node *arg = get_irn_n(irn, pos);
266
267                         if (!arch_irn_consider_in_reg_alloc(cls, arg))
268                                 continue;
269
270                         /* no edges to itself */
271                         if (irn == arg) {
272                                 continue;
273                         }
274
275                         insert_afe_edge(pbqp_alloc_env, irn, arg, pos);
276                 }
277         }
278         else if (is_Perm_Proj(irn)) { /* Perms */
279                 ir_node *arg = get_Perm_src(irn);
280                 if (!arch_irn_consider_in_reg_alloc(cls, arg))
281                         return;
282
283                 insert_afe_edge(pbqp_alloc_env, irn, arg, -1);
284         } else if (arch_register_req_is(req, should_be_same)) {
285                 const unsigned other = req->other_same;
286                 int            i;
287
288                 for (i = 0; 1U << i <= other; ++i) {
289                         if (other & (1U << i)) {
290                                 ir_node *other = get_irn_n(skip_Proj(irn), i);
291                                 if (!arch_irn_consider_in_reg_alloc(cls, other))
292                                         continue;
293
294                                 /* no edges to itself */
295                                 if (irn == other) {
296                                         continue;
297                                 }
298
299                                 insert_afe_edge(pbqp_alloc_env, irn, other, i);
300                         }
301                 }
302         }
303 }
304
305 static void create_pbqp_coloring_instance(ir_node *block, void *data)
306 {
307         be_pbqp_alloc_env_t         *pbqp_alloc_env     = (be_pbqp_alloc_env_t*)data;
308         be_lv_t                     *lv                 = pbqp_alloc_env->lv;
309         const arch_register_class_t *cls                = pbqp_alloc_env->cls;
310         plist_t                     *rpeo               = pbqp_alloc_env->rpeo;
311         pbqp_t                      *pbqp_inst          = pbqp_alloc_env->pbqp_inst;
312         plist_t                     *temp_list          = plist_new();
313         plist_element_t             *el;
314         ir_nodeset_t                 live_nodes;
315 #if USE_BIPARTIT_MATCHING
316         int                         *assignment         = ALLOCAN(int, cls->n_regs);
317 #else
318         unsigned                    *restr_nodes        = pbqp_alloc_env->restr_nodes;
319         pqueue_t                    *restr_nodes_queue  = new_pqueue();
320         pqueue_t                    *queue              = new_pqueue();
321         plist_t                     *sorted_list        = plist_new();
322         ir_node                     *last_element       = NULL;
323 #endif
324
325         /* first, determine the pressure */
326         /* (this is only for compatibility with copymin optimization, it's not needed for pbqp coloring) */
327         create_borders(block, pbqp_alloc_env->env);
328
329         /* calculate living nodes for the first step */
330         ir_nodeset_init(&live_nodes);
331         be_liveness_end_of_block(lv, cls, block, &live_nodes);
332
333         /* create pbqp nodes, interference edges and reverse perfect elimination order */
334         sched_foreach_reverse(block, irn) {
335                 be_foreach_value(irn, value,
336                         if (!arch_irn_consider_in_reg_alloc(cls, value))
337                                 continue;
338
339                         /* create pbqp source node if it dosn't exist */
340                         if (!get_node(pbqp_inst, get_irn_idx(value)))
341                                 create_pbqp_node(pbqp_alloc_env, value);
342
343                         /* create nodes and interference edges */
344                         foreach_ir_nodeset(&live_nodes, live, iter) {
345                                 /* create pbqp source node if it dosn't exist */
346                                 if (!get_node(pbqp_inst, get_irn_idx(live)))
347                                         create_pbqp_node(pbqp_alloc_env, live);
348
349                                 /* no edges to itself */
350                                 if (value == live)
351                                         continue;
352
353                                 insert_ife_edge(pbqp_alloc_env, value, live);
354                         }
355                 );
356
357                 /* get living nodes for next step */
358                 if (!is_Phi(irn)) {
359                         be_liveness_transfer(cls, irn, &live_nodes);
360                 }
361
362 #if USE_BIPARTIT_MATCHING
363                 if (get_irn_mode(irn) == mode_T) {
364                         unsigned     clique_size         = 0;
365                         unsigned     n_alloc             = 0;
366                         pbqp_node   *clique[cls->n_regs];
367                         bipartite_t *bp                  = bipartite_new(cls->n_regs, cls->n_regs);
368
369                         /* add all proj after a perm to clique */
370                         foreach_out_edge(irn, edge) {
371                                 ir_node *proj = get_edge_src_irn(edge);
372
373                                 /* ignore node if it is not necessary for register allocation */
374                                 if (!arch_irn_consider_in_reg_alloc(cls, proj))
375                                         continue;
376
377                                 /* insert pbqp node into temp rpeo list of this block */
378                                 plist_insert_front(temp_list, get_node(pbqp_inst, get_irn_idx(proj)));
379
380                                 if(is_Perm_Proj(proj)) {
381                                         /* add proj to clique */
382                                         pbqp_node *clique_member = get_node(pbqp_inst,proj->node_idx);
383                                         vector    *costs         = clique_member->costs;
384                                         unsigned   idx           = 0;
385
386                                         clique[clique_size] = clique_member;
387
388                                         for(idx = 0; idx < costs->len; idx++) {
389                                                 if(costs->entries[idx].data != INF_COSTS) {
390                                                         bipartite_add(bp, clique_size, idx);
391                                                 }
392                                         }
393
394                                         /* increase node counter */
395                                         clique_size++;
396                                         n_alloc++;
397                                 }
398                         }
399
400                         if(clique_size > 0) {
401                                 plist_element_t *listElement;
402                                 foreach_plist(temp_list, listElement) {
403                                         pbqp_node *clique_candidate  = listElement->data;
404                                         unsigned   idx               = 0;
405                                         bool       isMember          = true;
406
407                                         /* clique size not bigger then register class size */
408                                         if(clique_size >= cls->n_regs) break;
409
410                                         for(idx = 0; idx < clique_size; idx++) {
411                                                 pbqp_node *member = clique[idx];
412
413                                                 if(member == clique_candidate) {
414                                                         isMember = false;
415                                                         break;
416                                                 }
417
418                                                 if(get_edge(pbqp_inst, member->index, clique_candidate->index) == NULL && get_edge(pbqp_inst, clique_candidate->index, member->index) == NULL) {
419                                                         isMember = false;
420                                                         break;
421                                                 }
422                                         }
423
424                                         /* goto next list element if current node is not a member of the clique */
425                                         if(!isMember) { continue; }
426
427                                         /* add candidate to clique */
428                                         clique[clique_size] = clique_candidate;
429
430                                         vector *costs = clique_candidate->costs;
431                                         for(idx = 0; idx < costs->len; idx++) {
432                                                 if(costs->entries[idx].data != INF_COSTS) {
433                                                         bipartite_add(bp, clique_size, idx);
434                                                 }
435                                         }
436
437                                         /* increase node counter */
438                                         clique_size++;
439                                 }
440                         }
441
442                         /* solve bipartite matching */
443                         bipartite_matching(bp, assignment);
444
445                         /* assign colors */
446                         unsigned nodeIdx = 0;
447                         for(nodeIdx = 0; nodeIdx < clique_size; nodeIdx++) {
448                                 vector *costs = clique[nodeIdx]->costs;
449                                 int     idx;
450                                 for(idx = 0; idx < (int)costs->len; idx++) {
451                                         if(assignment[nodeIdx] != idx) {
452                                                 costs->entries[idx].data = INF_COSTS;
453                                         }
454                                 }
455                                 assert(assignment[nodeIdx] >= 0 && "there must have been a register assigned (node not register pressure faithful?)");
456                         }
457
458                         /* free memory */
459                         bipartite_free(bp);
460                 }
461                 else {
462                         if (arch_irn_consider_in_reg_alloc(cls, irn)) {
463                                 plist_insert_front(temp_list, get_node(pbqp_inst, get_irn_idx(irn)));
464                         }
465                 }
466 #else
467                 /* order nodes for perfect elimination order */
468                 if (get_irn_mode(irn) == mode_T) {
469                         bool allHaveIFEdges = true;
470                         foreach_out_edge(irn, edge) {
471                                 ir_node *proj = get_edge_src_irn(edge);
472                                 if (!arch_irn_consider_in_reg_alloc(cls, proj))
473                                         continue;
474
475                                 /* insert proj node into priority queue (descending by the number of interference edges) */
476                                 if (get_free_regs(restr_nodes, cls, proj) <= 4) {
477                                         pqueue_put(restr_nodes_queue, proj, pbqp_alloc_env->ife_edge_num[get_irn_idx(proj)]);
478                                 }
479                                 else {
480                                         pqueue_put(queue, proj, pbqp_alloc_env->ife_edge_num[get_irn_idx(proj)]);
481                                 }
482
483                                 /* skip last step if there is no last_element */
484                                 if(last_element == NULL)
485                                         continue;
486
487                                 /* check if proj has an if edge to last_element (at this time pbqp contains only if edges) */
488                                 if(get_edge(pbqp_inst, proj->node_idx, last_element->node_idx) == NULL && get_edge(pbqp_inst, last_element->node_idx, proj->node_idx) == NULL) {
489                                         allHaveIFEdges = false; /* there is no if edge between proj and last_element */
490                                 }
491                         }
492
493                         if(last_element != NULL && allHaveIFEdges) {
494                                 if (get_free_regs(restr_nodes, cls, last_element) <= 4) {
495                                         pqueue_put(restr_nodes_queue, last_element, pbqp_alloc_env->ife_edge_num[get_irn_idx(last_element)]);
496                                 }
497                                 else {
498                                         pqueue_put(queue, last_element, pbqp_alloc_env->ife_edge_num[get_irn_idx(last_element)]);
499                                 }
500                                 plist_erase(temp_list, plist_find_value(temp_list, get_node(pbqp_inst, last_element->node_idx)));
501                                 last_element = NULL;
502                         }
503
504                         /* first insert all restricted proj nodes */
505                         while (!pqueue_empty(restr_nodes_queue)) {
506                                 ir_node *node = (ir_node*)pqueue_pop_front(restr_nodes_queue);
507                                 plist_insert_front(sorted_list, get_node(pbqp_inst, get_irn_idx(node)));
508                         }
509
510                         /* insert proj nodes descending by their number of interference edges */
511                         while (!pqueue_empty(queue)) {
512                                 ir_node *node = (ir_node*)pqueue_pop_front(queue);
513                                 plist_insert_front(sorted_list, get_node(pbqp_inst, get_irn_idx(node)));
514                         }
515
516                         /* invert sorted list */
517                         foreach_plist(sorted_list, el) {
518                                 plist_insert_front(temp_list, el->data);
519                         }
520
521                         plist_clear(sorted_list);
522
523                 }
524                 else {
525                         if (arch_irn_consider_in_reg_alloc(cls, irn)) {
526                                 // remember last colorable node
527                                 last_element = irn;
528                                 plist_insert_front(temp_list, get_node(pbqp_inst, get_irn_idx(irn)));
529                         }
530                         else {
531                                 // node not colorable, so ignore it
532                                 last_element = NULL;
533                         }
534                 }
535 #endif
536         }
537
538         /* add the temp rpeo list of this block to the global reverse perfect elimination order list*/
539         foreach_plist(temp_list, el) {
540                 plist_insert_back(rpeo, el->data);
541         }
542
543         /* free reserved memory */
544         ir_nodeset_destroy(&live_nodes);
545         plist_free(temp_list);
546 #if USE_BIPARTIT_MATCHING
547 #else
548         plist_free(sorted_list);
549         del_pqueue(queue);
550         del_pqueue(restr_nodes_queue);
551 #endif
552 }
553
554 static void insert_perms(ir_node *block, void *data)
555 {
556         be_chordal_env_t *env    = (be_chordal_env_t*)data;
557         ir_node          *irn;
558
559         for (irn = sched_first(block); !sched_is_end(irn);) {
560                 ir_node   *const next = sched_next(irn);
561                 be_insn_t *      insn = be_scan_insn(env, irn);
562                 if (insn)
563                         pre_process_constraints(env, &insn);
564
565                 irn = next;
566         }
567 }
568
569 static void be_pbqp_coloring(be_chordal_env_t *env)
570 {
571         ir_graph                    *irg            = env->irg;
572         const arch_register_class_t *cls            = env->cls;
573         be_lv_t                     *lv             = NULL;
574         plist_element_t             *element        = NULL;
575         unsigned                     colors_n       = arch_register_class_n_regs(cls);
576         be_pbqp_alloc_env_t          pbqp_alloc_env;
577         unsigned                     col;
578         unsigned                     row;
579         pbqp_matrix_t               *ife_matrix;
580         num                          solution;
581 #if KAPS_DUMP
582         FILE                        *file_before;
583 #endif
584 #if TIMER
585         ir_timer_t *t_ra_pbqp_alloc_create     = ir_timer_new();
586         ir_timer_t *t_ra_pbqp_alloc_solve      = ir_timer_new();
587         ir_timer_t *t_ra_pbqp_alloc_create_aff = ir_timer_new();
588
589         printf("#### ----- === Allocating registers of %s (%s) ===\n", cls->name, get_entity_name(get_irg_entity(irg)));
590 #endif
591         be_assure_live_sets(irg);
592         lv = be_get_irg_liveness(irg);
593
594         /* insert perms */
595         assure_doms(irg);
596         dom_tree_walk_irg(irg, insert_perms, NULL, env);
597
598         /* dump graph after inserting perms */
599         if (env->opts->dump_flags & BE_CH_DUMP_CONSTR) {
600                 char buf[256];
601                 snprintf(buf, sizeof(buf), "%s-constr", cls->name);
602                 dump_ir_graph(irg, buf);
603         }
604
605         ir_calculate_execfreq_int_factors(&pbqp_alloc_env.execfreq_factors, irg);
606
607         /* initialize pbqp allocation data structure */
608         pbqp_alloc_env.pbqp_inst        = alloc_pbqp(get_irg_last_idx(irg));  /* initialize pbqp instance */
609         pbqp_alloc_env.cls              = cls;
610         pbqp_alloc_env.irg              = irg;
611         pbqp_alloc_env.lv               = lv;
612         pbqp_alloc_env.allocatable_regs = bitset_malloc(colors_n);
613         pbqp_alloc_env.rpeo             = plist_new();
614         pbqp_alloc_env.restr_nodes      = XMALLOCNZ(unsigned, get_irg_last_idx(irg));
615         pbqp_alloc_env.ife_edge_num     = XMALLOCNZ(unsigned, get_irg_last_idx(irg));
616         pbqp_alloc_env.env              = env;
617         be_put_allocatable_regs(irg, cls, pbqp_alloc_env.allocatable_regs);
618
619
620         /* create costs matrix template for interference edges */
621         ife_matrix = pbqp_matrix_alloc(pbqp_alloc_env.pbqp_inst, colors_n, colors_n);
622         /* set costs */
623         for (row = 0, col = 0; row < colors_n; row++, col++)
624                 pbqp_matrix_set(ife_matrix, row, col, INF_COSTS);
625
626         pbqp_alloc_env.ife_matrix_template = ife_matrix;
627
628
629         if (!use_exec_freq) {
630                 /* create costs matrix template for affinity edges */
631                 pbqp_matrix_t *afe_matrix = pbqp_matrix_alloc(pbqp_alloc_env.pbqp_inst, colors_n, colors_n);
632                 /* set costs */
633                 for (row = 0; row < colors_n; row++) {
634                         for (col = 0; col < colors_n; col++) {
635                                 if (row != col)
636                                         pbqp_matrix_set(afe_matrix, row, col, 2);
637                         }
638                 }
639                 pbqp_alloc_env.aff_matrix_template = afe_matrix;
640         }
641
642
643         /* create pbqp instance */
644 #if TIMER
645         ir_timer_reset_and_start(t_ra_pbqp_alloc_create);
646 #endif
647         assure_doms(irg);
648         dom_tree_walk_irg(irg, create_pbqp_coloring_instance , NULL, &pbqp_alloc_env);
649 #if TIMER
650         ir_timer_stop(t_ra_pbqp_alloc_create);
651 #endif
652
653
654         /* set up affinity edges */
655 #if TIMER
656         ir_timer_reset_and_start(t_ra_pbqp_alloc_create_aff);
657 #endif
658         foreach_plist(pbqp_alloc_env.rpeo, element) {
659                 pbqp_node_t *node = (pbqp_node_t*)element->data;
660                 ir_node     *irn  = get_idx_irn(irg, node->index);
661
662                 create_affinity_edges(irn, &pbqp_alloc_env);
663         }
664 #if TIMER
665         ir_timer_stop(t_ra_pbqp_alloc_create_aff);
666 #endif
667
668
669 #if KAPS_DUMP
670         // dump graph before solving pbqp
671         file_before = my_open(env, "", "-pbqp_coloring.html");
672         set_dumpfile(pbqp_alloc_env.pbqp_inst, file_before);
673 #endif
674
675         /* print out reverse perfect elimination order */
676 #if PRINT_RPEO
677         {
678                 plist_element_t *elements;
679                 foreach_plist(pbqp_alloc_env.rpeo, elements) {
680                         pbqp_node_t *node = elements->data;
681                         printf(" %d(%ld);", node->index, get_idx_irn(irg, node->index)->node_nr);
682                 }
683                 printf("\n");
684         }
685 #endif
686
687         /* solve pbqp instance */
688 #if TIMER
689         ir_timer_reset_and_start(t_ra_pbqp_alloc_solve);
690 #endif
691         if(use_late_decision) {
692                 solve_pbqp_heuristical_co_ld(pbqp_alloc_env.pbqp_inst,pbqp_alloc_env.rpeo);
693         }
694         else {
695                 solve_pbqp_heuristical_co(pbqp_alloc_env.pbqp_inst,pbqp_alloc_env.rpeo);
696         }
697 #if TIMER
698         ir_timer_stop(t_ra_pbqp_alloc_solve);
699 #endif
700
701
702         solution = get_solution(pbqp_alloc_env.pbqp_inst);
703         if (solution == INF_COSTS)
704                 panic("No PBQP solution found");
705
706
707         /* assign colors */
708         foreach_plist(pbqp_alloc_env.rpeo, element) {
709                 pbqp_node_t           *node  = (pbqp_node_t*)element->data;
710                 ir_node               *irn   = get_idx_irn(irg, node->index);
711                 num                    color = get_node_solution(pbqp_alloc_env.pbqp_inst, node->index);
712                 const arch_register_t *reg   = arch_register_for_index(cls, color);
713
714                 arch_set_irn_register(irn, reg);
715         }
716
717
718 #if TIMER
719         printf("PBQP alloc create:     %10.3lf msec\n",
720                (double)ir_timer_elapsed_usec(t_ra_pbqp_alloc_create) / 1000.0);
721         printf("PBQP alloc solve:      %10.3lf msec\n",
722                (double)ir_timer_elapsed_usec(t_ra_pbqp_alloc_solve) / 1000.0);
723         printf("PBQP alloc create aff: %10.3lf msec\n",
724                (double)ir_timer_elapsed_usec(t_ra_pbqp_alloc_create_aff) / 1000.0);
725 #endif
726
727
728         /* free reserved memory */
729 #if KAPS_DUMP
730         fclose(file_before);
731 #endif
732         bitset_free(pbqp_alloc_env.allocatable_regs);
733         free_pbqp(pbqp_alloc_env.pbqp_inst);
734         plist_free(pbqp_alloc_env.rpeo);
735         xfree(pbqp_alloc_env.restr_nodes);
736         xfree(pbqp_alloc_env.ife_edge_num);
737 }
738
739
740 /**
741  * Initializes this module.
742  */
743 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_pbqp_coloring)
744 void be_init_pbqp_coloring(void)
745 {
746         lc_opt_entry_t *be_grp       = lc_opt_get_grp(firm_opt_get_root(), "be");
747         lc_opt_entry_t *ra_grp       = lc_opt_get_grp(be_grp, "ra");
748         lc_opt_entry_t *chordal_grp  = lc_opt_get_grp(ra_grp, "chordal");
749         lc_opt_entry_t *coloring_grp = lc_opt_get_grp(chordal_grp, "coloring");
750         lc_opt_entry_t *pbqp_grp     = lc_opt_get_grp(coloring_grp, "pbqp");
751
752         static be_ra_chordal_coloring_t coloring = {
753                 be_pbqp_coloring
754         };
755
756         lc_opt_add_table(pbqp_grp, options);
757         be_register_chordal_coloring("pbqp", &coloring);
758 }