Added new arch interface
[libfirm] / ir / be / becopyilp.c
1 /**
2  * Minimizing copies with an exact algorithm using mixed integer programming (MIP).
3  * Problem statement as a 'quadratic 0-1 program with linear constraints' with
4  * n binary variables. Constraints are knapsack (enforce color for each node) and
5  * cliques of ifg (interference constraints).
6  * Transformation into a 'mixed integer program' with n binary variables and
7  * additional 2n real variables. Constraints are the above the transformed
8  * objective function and 'complementary conditions' for two var classes.
9  * @author Daniel Grund
10  *
11  * NOTE: Unfortunately no good solver is available locally (or even for linking)
12  *       We use CPLEX 9.0 which runs on a machine residing at the Rechenzentrum.
13  * @date 12.04.2005
14  */
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif
18
19 #ifdef HAVE_ALLOCA_H
20 #include <alloca.h>
21 #endif
22 #ifdef HAVE_MALLOC_H
23 #include <malloc.h>
24 #endif
25
26 #include "xmalloc.h"
27 #include "becopyopt.h"
28 #include "becopystat.h"
29
30 #undef DUMP_MATRICES            /**< dumps all matrices completely. only recommended for small problems */
31 #define DUMP_MILP                       /**< dumps the problem as Mixed Integer Linear Programming in "CPLEX"-MPS format. NOT fixed-column-MPS. */
32 #undef DO_SOLVE                         /**< solve the MPS output with CPLEX */
33 #undef DELETE_FILES             /**< deletes all dumped files after use */
34
35 /* CPLEX-account related stuff */
36 #define SSH_USER_HOST "kb61@sp-smp.rz.uni-karlsruhe.de"
37 #define SSH_PASSWD_FILE "/ben/daniel/.smppw"
38 #define EXPECT_FILENAME "runme" /** name of the expect-script */
39
40 #define DEBUG_LVL 0 //SET_LEVEL_1
41 static firm_dbg_module_t *dbg = NULL;
42
43 #define SLOTS_NUM2POS 256
44 #define SLOTS_LIVING 32
45
46 /* get_weight represents the _gain_ if node n and m have the same color. */
47 #define get_weight(n,m) 1
48
49 /**
50  * A type storing names of the x variables in the form x[NUMBER]_[COLOR]
51  */
52 typedef struct _x_name_t {
53         int n, c;
54 } x_name_t;
55
56 /**
57  * For each node taking part in the opt-problem its position in the
58  * x-variable-vector is stored in a set. This set maps the node-nr (given by
59  * benumb) to the position in the vector.
60  */
61 typedef struct _num2pos_t {
62         int num, pos;
63 } num2pos_t;
64
65 /**
66  * A type storing the unmodified '0-1 quadratic program' of the form
67  * min f = xQx
68  * udN:  Ax  = e
69  *       Bx <= e
70  *        x \in {0, 1}
71  *
72  * This problem is called the original problem
73  */
74 typedef struct _problem_instance_t {
75         const copy_opt_t *co;                   /** the original copy_opt problem */
76         int x_dim, A_dim, B_dim;                /**< number of: x variables (equals Q_dim), rows in A, rows in B */
77         x_name_t *x;                                    /**< stores the names of the x variables. all possible colors for a node are ordered and occupy consecutive entries. lives in obstack ob. */
78         set *num2pos;                                   /**< maps node numbers to positions in x. */
79         sp_matrix_t *Q, *A, *B;                 /**< the (sparse) matrices of this problem */
80
81         /* needed only for linearizations */
82         int bigM, maxQij, minQij;
83
84         /* overhead needed to build this */
85         struct obstack ob;
86         int curr_color;
87         int curr_row;
88 } problem_instance_t;
89
90 /* Nodes have consecutive numbers so this hash shoud be fine */
91 #define HASH_NUM(num) num
92
93 static int set_cmp_num2pos(const void *x, const void *y, size_t size) {
94         return ((num2pos_t *)x)->num != ((num2pos_t *)y)->num;
95 }
96
97 /**
98  * Sets the first position of node with number num to pos.
99  * See x_name_t *x in _problem_instance_t.
100  */
101 static INLINE void pi_set_first_pos(problem_instance_t *pi, int num, int pos) {
102         num2pos_t find;
103         find.num = num;
104         find.pos = pos;
105         set_insert(pi->num2pos, &find, sizeof(find), HASH_NUM(num));
106 }
107
108 /**
109  * Get position by number. (First possible color)
110  * returns -1 if not found.
111  */
112 static INLINE int pi_get_first_pos(problem_instance_t *pi, int num) {
113         num2pos_t find, *found;
114         find.num = num;
115         found = set_find(pi->num2pos, &find, sizeof(find), HASH_NUM(num));
116         if (found) {
117                 assert(pi->x[found->pos].n == num && (found->pos == 0 || pi->x[found->pos-1].n != num) && "pi->num2pos is broken!");
118                 return found->pos;
119         } else
120                 return -1;
121 }
122
123 /**
124  * Get position by number and color.
125  * returns -1 if not found.
126  */
127 static INLINE int pi_get_pos(problem_instance_t *pi, int num, int col) {
128         num2pos_t find, *found;
129         int pos;
130
131         find.num = num;
132         found = set_find(pi->num2pos, &find, sizeof(find), HASH_NUM(num));
133         if (!found)
134                 return -1;
135         pos = found->pos;
136         while (pos < pi->x_dim && pi->x[pos].n == num && pi->x[pos].c < col)
137                 pos++;
138
139         if (pi->x[pos].n == num && pi->x[pos].c == col)
140                 return pos;
141         else
142                 return -1;
143 }
144
145 #ifdef DUMP_MATRICES
146 /**
147  * Dump the raw matrices of the problem to a file for debugging.
148  */
149 static void pi_dump_matrices(problem_instance_t *pi) {
150         int i;
151         FILE *out = ffopen(pi->co->name, "matrix", "wt");
152
153         DBG((dbg, LEVEL_1, "Dumping raw...\n"));
154         fprintf(out, "\n\nx-names =\n");
155         for (i=0; i<pi->x_dim; ++i)
156                 fprintf(out, "%5d %2d\n", pi->x[i].n, pi->x[i].c);
157
158         fprintf(out, "\n\n-Q =\n");
159         matrix_dump(pi->Q, out, -1);
160
161         fprintf(out, "\n\nA =\n");
162         matrix_dump(pi->A, out, 1);
163
164         fprintf(out, "\n\nB =\n");
165         matrix_dump(pi->B, out, 1);
166
167         fclose(out);
168 }
169 #endif
170
171 #ifdef DUMP_MILP
172 /**
173  * Dumps an mps file representing the problem. This is NOT the old-style,
174  * fixed-column format. Some white spaces are important, in general spaces
175  * are separators, MARKER-lines are used in COLUMN section to define binaries.
176  */
177 //BETTER use last 2 fields in COLUMNS section. See MPS docu for details
178 static void pi_dump_milp(problem_instance_t *pi) {
179         int i, max_abs_Qij;
180         const matrix_elem_t *e;
181         bitset_t *good_row;
182         FILE *out = ffopen(pi->co->name, "milp", "wt");
183
184         DBG((dbg, LEVEL_1, "Dumping milp...\n"));
185         max_abs_Qij = pi->maxQij;
186         if (-pi->minQij > max_abs_Qij)
187                 max_abs_Qij = -pi->minQij;
188         pi->bigM = pi->A_dim * max_abs_Qij;
189         DBG((dbg, LEVEL_2, "BigM = %d\n", pi->bigM));
190
191         matrix_optimize(pi->Q);
192         good_row = bitset_alloca(pi->x_dim);
193         for (i=0; i<pi->x_dim; ++i)
194                 if (matrix_row_first(pi->Q, i))
195                         bitset_set(good_row, i);
196
197         fprintf(out, "NAME %s\n", pi->co->name);
198
199         fprintf(out, "ROWS\n");
200         fprintf(out, " N obj\n");
201         for (i=0; i<pi->x_dim; ++i)
202                 if (bitset_is_set(good_row, i))
203                         fprintf(out, " E cQ%d\n", i);
204         for (i=0; i<pi->A_dim; ++i)
205                 fprintf(out, " E cA%d\n", i);
206         for (i=0; i<pi->B_dim; ++i)
207                 fprintf(out, " L cB%d\n", i);
208         for (i=0; i<pi->x_dim; ++i)
209                 if (bitset_is_set(good_row, i))
210                         fprintf(out, " L cy%d\n", i);
211
212         fprintf(out, "COLUMNS\n");
213         /* the x vars come first */
214         /* mark them as binaries */
215         fprintf(out, "    MARKI0\t'MARKER'\t'INTORG'\n");
216         for (i=0; i<pi->x_dim; ++i) {
217                 /* participation in objective */
218                 if (bitset_is_set(good_row, i))
219                         fprintf(out, "    x%d_%d\tobj\t%d\n", pi->x[i].n, pi->x[i].c, -pi->bigM);
220                 /* in Q */
221                 matrix_foreach_in_col(pi->Q, i, e)
222                         fprintf(out, "    x%d_%d\tcQ%d\t%d\n", pi->x[i].n, pi->x[i].c, e->row, e->val);
223                 /* in A */
224                 matrix_foreach_in_col(pi->A, i, e)
225                         fprintf(out, "    x%d_%d\tcA%d\t%d\n", pi->x[i].n, pi->x[i].c, e->row, e->val);
226                 /* in B */
227                 matrix_foreach_in_col(pi->B, i, e)
228                         fprintf(out, "    x%d_%d\tcB%d\t%d\n", pi->x[i].n, pi->x[i].c, e->row, e->val);
229                 /* in y */
230                 if (bitset_is_set(good_row, i))
231                         fprintf(out, "    x%d_%d\tcy%d\t%d\n", pi->x[i].n, pi->x[i].c, i, 2*pi->bigM);
232         }
233
234         fprintf(out, "    MARKI1\t'MARKER'\t'INTEND'\n"); /* end of marking */
235
236         /* next the s vars */
237         for (i=0; i<pi->x_dim; ++i)
238                 if (bitset_is_set(good_row, i)) {
239                         /* participation in objective */
240                         fprintf(out, "    s%d_%d\tobj\t%d\n", pi->x[i].n, pi->x[i].c, 1);
241                         /* in Q */
242                         fprintf(out, "    s%d_%d\tcQ%d\t%d\n", pi->x[i].n, pi->x[i].c, i, -1);
243                 }
244
245         /* next the y vars */
246         for (i=0; i<pi->x_dim; ++i)
247                 if (bitset_is_set(good_row, i)) {
248                         /* in Q */
249                         fprintf(out, "    y%d_%d\tcQ%d\t%d\n", pi->x[i].n, pi->x[i].c, i, -1);
250                         /* in y */
251                         fprintf(out, "    y%d_%d\tcy%d\t%d\n", pi->x[i].n, pi->x[i].c, i, 1);
252                 }
253
254         fprintf(out, "RHS\n");
255         for (i=0; i<pi->x_dim; ++i)
256                 if (bitset_is_set(good_row, i))
257                         fprintf(out, "    rhs\tcQ%d\t%d\n", i, -pi->bigM);
258         for (i=0; i<pi->A_dim; ++i)
259                 fprintf(out, "    rhs\tcA%d\t%d\n", i, 1);
260         for (i=0; i<pi->B_dim; ++i)
261                 fprintf(out, "    rhs\tcB%d\t%d\n", i, 1);
262         for (i=0; i<pi->x_dim; ++i)
263                 if (bitset_is_set(good_row, i))
264                         fprintf(out, "    rhs\tcy%d\t%d\n", i, 2*pi->bigM);
265
266         fprintf(out, "ENDATA\n");
267         fclose(out);
268 }
269 #endif
270
271 #ifdef DO_SOLVE
272 /**
273  * Dumps the known solution to a file to make use of it
274  * as a starting solution respectively as a bound
275  */
276 static void pi_dump_start_sol(problem_instance_t *pi) {
277         int i;
278         FILE *out = ffopen(pi->co->name, "mst", "wt");
279         fprintf(out, "NAME\n");
280         for (i=0; i<pi->x_dim; ++i) {
281                 int val, n, c;
282                 n = pi->x[i].n;
283                 c = pi->x[i].c;
284                 if (get_irn_color(get_irn_for_graph_nr(pi->co->irg, n)) == c)
285                         val = 1;
286                 else
287                         val = 0;
288                 fprintf(out, "    x%d_%d\t%d\n", n, c, val);
289         }
290         fprintf(out, "ENDATA\n");
291         fclose(out);
292 }
293
294 /**
295  * Invoke an external solver
296  */
297 static void pi_solve_ilp(problem_instance_t *pi) {
298         FILE *out, *pwfile;
299         char passwd[128];
300
301         DBG((dbg, LEVEL_1, "Solving with CPLEX@RZ...\n"));
302         /* write command file for CPLEX */
303         out = ffopen(pi->co->name, "cmd", "wt");
304         fprintf(out, "set logfile %s.sol\n", pi->co->name);
305 #ifdef DUMP_MILP
306         fprintf(out, "read %s.milp mps\n", pi->co->name);
307 #endif
308 #ifdef DUMP_MIQP
309         fprintf(out, "read %s.miqp mps\n", pi->co->name);
310 #endif
311         fprintf(out, "read %s.mst\n", pi->co->name);
312         fprintf(out, "set mip strategy mipstart 1\n");
313         fprintf(out, "set mip emphasis 3\n");
314         fprintf(out, "optimize\n");
315         fprintf(out, "display solution variables 1-%d\n", pi->x_dim);
316         fprintf(out, "set logfile cplex.log\n");
317         fprintf(out, "quit\n");
318         fclose(out);
319
320         /* write expect-file for copying problem to RZ */
321         pwfile = fopen(SSH_PASSWD_FILE, "rt");
322         fgets(passwd, sizeof(passwd), pwfile);
323         fclose(pwfile);
324
325         out = ffopen(EXPECT_FILENAME, "exp", "wt");
326         fprintf(out, "#! /usr/bin/expect\n");
327         fprintf(out, "spawn scp %s.miqp %s.milp %s.mst %s.cmd %s:\n", pi->co->name, pi->co->name, pi->co->name, pi->co->name, SSH_USER_HOST); /* copy problem files */
328         fprintf(out, "expect \"word:\"\nsend \"%s\\n\"\ninteract\n", passwd);
329
330         fprintf(out, "spawn ssh %s \"./cplex90 < %s.cmd\"\n", SSH_USER_HOST, pi->co->name); /* solve */
331         fprintf(out, "expect \"word:\"\nsend \"%s\\n\"\ninteract\n", passwd);
332
333         fprintf(out, "spawn scp %s:%s.sol .\n", SSH_USER_HOST, pi->co->name); /*copy back solution */
334         fprintf(out, "expect \"word:\"\nsend \"%s\\n\"\ninteract\n", passwd);
335
336         fprintf(out, "spawn ssh %s ./dell\n", SSH_USER_HOST); /* clean files on server */
337         fprintf(out, "expect \"word:\"\nsend \"%s\\n\"\ninteract\n", passwd);
338         fclose(out);
339
340         /* call the expect script */
341         chmod(EXPECT_FILENAME ".exp", 0700);
342         system(EXPECT_FILENAME ".exp");
343 }
344
345 /**
346  * Sets the colors of irns according to the values of variables found in the
347  * output file of the solver.
348  */
349 static void pi_apply_solution(problem_instance_t *pi) {
350         FILE *in = ffopen(pi->co->name, "sol", "rt");
351
352         if (!in)
353                 return;
354         DBG((dbg, LEVEL_1, "Applying solution...\n"));
355         while (!feof(in)) {
356                 char buf[1024];
357                 int num = -1, col = -1, val = -1;
358
359                 fgets(buf, sizeof(buf), in);
360                 DBG((dbg, LEVEL_3, "Line: %s", buf));
361
362                 if (strcmp(buf, "No integer feasible solution exists.") == 0)
363                         assert(0 && "CPLEX says: No integer feasible solution exists!");
364
365                 if (strcmp(buf, "TODO Out of memory") == 0) {}
366
367 #ifdef DO_STAT
368                 {
369                         /* solution time */
370                         float sol_time;
371                         int iter;
372                         if (sscanf(buf, "Solution time = %f sec. Iterations = %d", &sol_time, &iter) == 2) {
373                                 DBG((dbg, LEVEL_2, " Time: %f Iter: %d\n", sol_time, iter));
374                                 curr_vals[I_ILP_TIME] += 10 * sol_time;
375                                 curr_vals[I_ILP_ITER] += iter;
376                         }
377                 }
378 #endif
379
380                 /* variable value */
381                 if (sscanf(buf, "x%d_%d %d", &num, &col, &val) == 3 && val == 1) {
382                         DBG((dbg, LEVEL_2, " x%d_%d = %d\n", num, col, val));
383                         set_irn_color(get_irn_for_graph_nr(pi->co->irg, num), col);
384                 }
385         }
386         fclose(in);
387 }
388 #endif /* DO_SOLVE */
389
390 #ifdef DELETE_FILES
391 static void pi_delete_files(problem_instance_t *pi) {
392         char buf[1024];
393         int end = snprintf(buf, sizeof(buf), "%s", pi->co->name);
394         DBG((dbg, LEVEL_1, "Deleting files...\n"));
395 #ifdef DUMP_MATRICES
396         snprintf(buf+end, sizeof(buf)-end, ".matrix");
397         remove(buf);
398 #endif
399 #ifdef DUMP_MILP
400         snprintf(buf+end, sizeof(buf)-end, ".mps");
401         remove(buf);
402         snprintf(buf+end, sizeof(buf)-end, ".mst");
403         remove(buf);
404         snprintf(buf+end, sizeof(buf)-end, ".cmd");
405         remove(buf);
406         remove(EXPECT_FILENAME ".exp");
407 #endif
408 #ifdef DO_SOLVE
409         snprintf(buf+end, sizeof(buf)-end, ".sol");
410         remove(buf);
411 #endif
412 }
413 #endif
414
415 /**
416  * Collects all irns in currently processed register class
417  */
418 static void pi_collect_x_names(ir_node *block, void *env) {
419         problem_instance_t *pi = env;
420         struct list_head *head = &get_ra_block_info(block)->border_head;
421         border_t *curr;
422         bitset_t *pos_regs = bitset_alloca(pi->co->cls->n_regs);
423
424         list_for_each_entry_reverse(border_t, curr, head, list)
425                 if (curr->is_def && curr->is_real) {
426                         x_name_t xx;
427                         pi->A_dim++;                    /* one knapsack constraint for each node */
428
429                         xx.n = get_irn_graph_nr(curr->irn);
430                         pi_set_first_pos(pi, xx.n, pi->x_dim);
431
432                         // iterate over all possible colors in order
433                         bitset_clear_all(pos_regs);
434                         pi->co->isa->get_allocatable_regs(curr->irn, pi->co->cls, pos_regs);
435                         bitset_foreach(pos_regs, xx.c) {
436                                 DBG((dbg, LEVEL_2, "Adding %n %d\n", curr->irn, xx.c));
437                                 obstack_grow(&pi->ob, &xx, sizeof(xx));
438                                 pi->x_dim++;            /* one x variable for each node and color */
439                         }
440                 }
441 }
442
443 /**
444  * Checks if all nodes in living are live_out in block block.
445  */
446 static INLINE int all_live_in(ir_node *block, pset *living) {
447         ir_node *n;
448         for (n = pset_first(living); n; n = pset_next(living))
449                 if (!is_live_in(block, n)) {
450                         pset_break(living);
451                         return 0;
452                 }
453         return 1;
454 }
455
456 /**
457  * Finds cliques in the interference graph, considering only nodes
458  * for which the color pi->curr_color is possible. Finds only 'maximal-cliques',
459  * viz cliques which are not conatained in another one.
460  * This is used for the matrix B.
461  */
462 static void pi_clique_finder(ir_node *block, void *env) {
463         problem_instance_t *pi = env;
464         enum phase_t {growing, shrinking} phase = growing;
465         struct list_head *head = &get_ra_block_info(block)->border_head;
466         border_t *b;
467         pset *living = pset_new_ptr(SLOTS_LIVING);
468
469         list_for_each_entry_reverse(border_t, b, head, list) {
470                 const ir_node *irn = b->irn;
471
472                 if (b->is_def) {
473                         DBG((dbg, LEVEL_2, "Def %n\n", irn));
474                         pset_insert_ptr(living, irn);
475                         phase = growing;
476                 } else { /* is_use */
477                         DBG((dbg, LEVEL_2, "Use %n\n", irn));
478
479                         /* before shrinking the set, store the current 'maximum' clique;
480                          * do NOT if clique is a single node
481                          * do NOT if all values are live_in (in this case they were contained in a live-out clique elsewhere) */
482                         if (phase == growing && pset_count(living) >= 2 && !all_live_in(block, living)) {
483                                 ir_node *n;
484                                 for (n = pset_first(living); n; n = pset_next(living)) {
485                                         int pos = pi_get_pos(pi, get_irn_graph_nr(n), pi->curr_color);
486                                         matrix_set(pi->B, pi->curr_row, pos, 1);
487                                         DBG((dbg, LEVEL_2, "B[%d, %d] := %d\n", pi->curr_row, pos, 1));
488                                 }
489                                 pi->curr_row++;
490                         }
491                         pset_remove_ptr(living, irn);
492                         phase = shrinking;
493                 }
494         }
495
496         del_pset(living);
497 }
498
499 /**
500  * Generate the initial problem matrices and vectors.
501  */
502 static problem_instance_t *new_pi(const copy_opt_t *co) {
503         problem_instance_t *pi;
504
505         DBG((dbg, LEVEL_1, "Generating new instance...\n"));
506         pi = xcalloc(1, sizeof(*pi));
507         pi->co = co;
508         pi->num2pos = new_set(set_cmp_num2pos, SLOTS_NUM2POS);
509         pi->bigM = 1;
510
511         /* Vector x
512          * one entry per node and possible color */
513         obstack_init(&pi->ob);
514         dom_tree_walk_irg(co->irg, pi_collect_x_names, NULL, pi);
515         pi->x = obstack_finish(&pi->ob);
516
517         /* Matrix Q
518          * weights for the 'same-color-optimization' target */
519         {
520                 unit_t *curr;
521                 pi->Q = new_matrix(pi->x_dim, pi->x_dim);
522
523                 list_for_each_entry(unit_t, curr, &co->units, units) {
524                         const ir_node *root, *arg;
525                         int rootnr, argnr;
526                         unsigned rootpos, argpos;
527                         int i;
528
529                         root = curr->nodes[0];
530                         rootnr = get_irn_graph_nr(root);
531                         rootpos = pi_get_first_pos(pi, rootnr);
532                         for (i = 1; i < curr->node_count; ++i) {
533                                 int weight = -get_weight(root, arg);
534                                 arg = curr->nodes[i];
535                                 argnr = get_irn_graph_nr(arg);
536                                 argpos = pi_get_first_pos(pi, argnr);
537
538                                 DBG((dbg, LEVEL_2, "Q[%n, %n] := %d\n", root, arg, weight));
539                                 /* for all colors root and arg have in common, set the weight for
540                                  * this pair in the objective function matrix Q */
541                                 while (rootpos < pi->x_dim && argpos < pi->x_dim &&
542                                                 pi->x[rootpos].n == rootnr && pi->x[argpos].n == argnr) {
543                                         if (pi->x[rootpos].c < pi->x[argpos].c)
544                                                 ++rootpos;
545                                         else if (pi->x[rootpos].c > pi->x[argpos].c)
546                                                 ++argpos;
547                                         else {
548                                                 matrix_set(pi->Q, rootpos++, argpos++, weight);
549
550                                                 if (weight < pi->minQij) {
551                                                         DBG((dbg, LEVEL_2, "minQij = %d\n", weight));
552                                                         pi->minQij = weight;
553                                                 }
554                                                 if (weight > pi->maxQij) {
555                                                         DBG((dbg, LEVEL_2, "maxQij = %d\n", weight));
556                                                         pi->maxQij = weight;
557                                                 }
558                                         }
559                                 }
560                         }
561                 }
562         }
563
564         /* Matrix A
565          * knapsack constraint for each node */
566         {
567                 int row = 0, col = 0;
568                 pi->A = new_matrix(pi->A_dim, pi->x_dim);
569                 while (col < pi->x_dim) {
570                         int curr_n = pi->x[col].n;
571                         while (col < pi->x_dim && pi->x[col].n == curr_n) {
572                                 DBG((dbg, LEVEL_2, "A[%d, %d] := %d\n", row, col, 1));
573                                 matrix_set(pi->A, row, col++, 1);
574                         }
575                         ++row;
576                 }
577                 assert(row == pi->A_dim);
578         }
579
580         /* Matrix B
581          * interference constraints using exactly those cliques not contained in others. */
582         {
583                 int color, expected_clipques = pi->A_dim/4 * pi->co->cls->n_regs;
584                 pi->B = new_matrix(expected_clipques, pi->x_dim);
585                 for (color = 0; color < pi->co->cls->n_regs; ++color) {
586                         pi->curr_color = color;
587                         dom_tree_walk_irg(pi->co->irg, pi_clique_finder, NULL, pi);
588                 }
589                 pi->B_dim = matrix_get_rowcount(pi->B);
590         }
591
592         return pi;
593 }
594
595 /**
596  * clean the problem instance
597  */
598 static void free_pi(problem_instance_t *pi) {
599         DBG((dbg, LEVEL_1, "Generating new instance...\n"));
600         del_matrix(pi->Q);
601         del_matrix(pi->A);
602         del_matrix(pi->B);
603         del_set(pi->num2pos);
604         obstack_free(&pi->ob, NULL);
605         xfree(pi);
606 }
607
608 void co_ilp_opt(copy_opt_t *co) {
609         problem_instance_t *pi;
610
611         dbg = firm_dbg_register("ir.be.copyoptilp");
612         firm_dbg_set_mask(dbg, DEBUG_LVL);
613         if (!strcmp(co->name, DEBUG_IRG))
614                 firm_dbg_set_mask(dbg, -1);
615
616         pi = new_pi(co);
617         DBG((dbg, 0, "\t\t\t %5d %5d %5d\n", pi->x_dim, pi->A_dim, pi->B_dim));
618
619         if (pi->x_dim > 0) {
620 #ifdef DUMP_MATRICES
621         pi_dump_matrices(pi);
622 #endif
623
624 #ifdef DUMP_MILP
625         pi_dump_milp(pi);
626 #endif
627
628 #ifdef DO_SOLVE
629         pi_dump_start_sol(pi);
630         pi_solve_ilp(pi);
631         pi_apply_solution(pi);
632 #endif
633
634 #ifdef DELETE_FILES
635         pi_delete_files(pi);
636 #endif
637         }
638         free_pi(pi);
639 }