becopyilp: code cleanups
[libfirm] / ir / be / becopyilp2.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       ILP based copy minimization.
23  * @author      Daniel Grund
24  * @date        28.02.2006
25  *
26  * ILP formalization using G=(V, E, Q):
27  *  - 2 class of variables: coloring vars x_ic   and   equal color vars y_ij
28  *  - Path constraints
29  *  - Clique-star constraints
30  *
31  *
32  * \min \sum_{ (i,j) \in Q }  w_ij y_ij
33  *
34  *     \sum_c x_nc           =  1           n \in N, c \in C
35  *
36  *     x_nc                  =  0           n \in N, c \not\in C(n)
37  *
38  *     \sum x_nc            <=  1           x_nc \in Clique \in AllCliques,  c \in C
39  *
40  *     \sum_{e \in p} y_e   >=  1           p \in P      path constraints
41  *
42  *     \sum_{e \in cs} y_e  >= |cs| - 1     cs \in CP    clique-star constraints
43  *
44  *     x_nc, y_ij \in N,   w_ij \in R^+
45  */
46 #include "config.h"
47
48 #include "bitset.h"
49 #include "raw_bitset.h"
50 #include "pdeq.h"
51
52 #include "util.h"
53 #include "irgwalk.h"
54 #include "becopyilp_t.h"
55 #include "beifg.h"
56 #include "besched.h"
57 #include "bemodule.h"
58
59 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
60
61 typedef struct local_env_t {
62         int       first_x_var;
63         int       last_x_var;
64         unsigned  n_colors;
65         unsigned *normal_colors;
66 } local_env_t;
67
68 static void make_color_var_name(char *buf, size_t buf_size,
69                                 const ir_node *node, unsigned color)
70 {
71         unsigned node_idx = get_irn_idx(node);
72         snprintf(buf, buf_size, "x_%u_%u", node_idx, color);
73 }
74
75 static void build_coloring_cstr(ilp_env_t *ienv)
76 {
77         local_env_t *lenv   = ienv->env;
78         be_ifg_t    *ifg    = ienv->co->cenv->ifg;
79         unsigned     n_regs = arch_register_class_n_regs(ienv->co->cls);
80         nodes_iter_t iter;
81         unsigned    *colors;
82         ir_node     *irn;
83         char         buf[32];
84
85         rbitset_alloca(colors, n_regs);
86
87         be_ifg_foreach_node(ifg, &iter, irn) {
88                 const arch_register_req_t *req;
89                 unsigned                   col;
90                 int                        cst_idx;
91                 unsigned                   curr_node_color;
92
93                 if (sr_is_removed(ienv->sr, irn))
94                         continue;
95
96                 req = arch_get_irn_register_req(irn);
97
98                 /* get assignable colors */
99                 if (arch_register_req_is(req, limited)) {
100                         rbitset_copy(colors, req->limited, n_regs);
101                 } else {
102                         rbitset_copy(colors, lenv->normal_colors, n_regs);
103                 }
104
105                 /* add the coloring constraint */
106                 cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_equal, 1.0);
107
108                 curr_node_color = get_irn_col(irn);
109                 for (col = 0; col < n_regs; ++col) {
110                         int    var_idx;
111                         double val;
112                         if (!rbitset_is_set(colors, col))
113                                 continue;
114
115                         make_color_var_name(buf, sizeof(buf), irn, col);
116                         var_idx = lpp_add_var(ienv->lp, buf, lpp_binary, 0.0);
117                         lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1);
118
119                         val = (col == curr_node_color) ? 1.0 : 0.0;
120                         lpp_set_start_value(ienv->lp, var_idx, val);
121
122                         lenv->last_x_var = var_idx;
123                         if (lenv->first_x_var == -1)
124                                 lenv->first_x_var = var_idx;
125                 }
126
127                 /* add register constraint constraints */
128                 for (col = 0; col < n_regs; ++col) {
129                         int cst_idx;
130                         int var_idx;
131                         if (rbitset_is_set(colors, col))
132                                 continue;
133
134                         make_color_var_name(buf, sizeof(buf), irn, col);
135                         cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_equal, 0.0);
136                         var_idx = lpp_add_var(ienv->lp, buf, lpp_binary, 0.0);
137                         lpp_set_start_value(ienv->lp, var_idx, 0.0);
138                         lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1);
139
140                         lenv->last_x_var = var_idx;
141                 }
142         }
143 }
144
145 static void build_interference_cstr(ilp_env_t *ienv)
146 {
147         lpp_t         *lpp      = ienv->lp;
148         local_env_t   *lenv     = ienv->env;
149         be_ifg_t      *ifg      = ienv->co->cenv->ifg;
150         unsigned       n_colors = lenv->n_colors;
151         ir_node      **clique   = ALLOCAN(ir_node*, n_colors);
152         cliques_iter_t iter;
153         int            size;
154         unsigned       col;
155         int            i;
156
157         /* for each maximal clique */
158         be_ifg_foreach_clique(ifg, &iter, clique, &size) {
159                 unsigned realsize = 0;
160
161                 for (i=0; i<size; ++i) {
162                         if (!sr_is_removed(ienv->sr, clique[i]))
163                                 ++realsize;
164                 }
165
166                 if (realsize < 2)
167                         continue;
168
169                 /* for all colors */
170                 for (col=0; col<n_colors; ++col) {
171                         int cst_idx = lpp_add_cst(lpp, NULL, lpp_less_equal, 1.0);
172
173                         /* for each member of this clique */
174                         for (i=0; i<size; ++i) {
175                                 ir_node *irn = clique[i];
176                                 char     buf[32];
177                                 int      var_idx;
178
179                                 if (sr_is_removed(ienv->sr, irn))
180                                         continue;
181
182                                 make_color_var_name(buf, sizeof(buf), irn, col);
183                                 var_idx = lpp_get_var_idx(lpp, buf);
184                                 lpp_set_factor_fast(lpp, cst_idx, var_idx, 1);
185                         }
186                 }
187         }
188 }
189
190 static void make_affinity_var_name(char *buf, size_t buf_size,
191                                    const ir_node *node1, const ir_node *node2)
192 {
193         unsigned n1 = get_irn_idx(node1);
194         unsigned n2 = get_irn_idx(node2);
195         if (n1 < n2) {
196                 snprintf(buf, buf_size, "y_%u_%u", n1, n2);
197         } else {
198                 snprintf(buf, buf_size, "y_%u_%u", n2, n1);
199         }
200 }
201
202
203 /**
204  * TODO: Remove the dependency of the opt-units data structure
205  *       by walking over all affinity edges. Graph structure
206  *       does not provide this walker, yet.
207  */
208 static void build_affinity_cstr(ilp_env_t *ienv)
209 {
210         local_env_t *lenv     = ienv->env;
211         unsigned     n_colors = lenv->n_colors;
212         unit_t      *curr;
213
214         /* for all optimization units */
215         list_for_each_entry(unit_t, curr, &ienv->co->units, units) {
216                 ir_node *root     = curr->nodes[0];
217                 unsigned root_col = get_irn_col(root);
218                 int      i;
219
220                 for (i = 1; i < curr->node_count; ++i) {
221                         ir_node *arg     = curr->nodes[i];
222                         unsigned arg_col = get_irn_col(arg);
223                         double   val;
224                         char     buf[32];
225                         unsigned col;
226                         int      y_idx;
227
228                         /* add a new affinity variable */
229                         make_affinity_var_name(buf, sizeof(buf), arg, root);
230                         y_idx = lpp_add_var(ienv->lp, buf, lpp_binary, curr->costs[i]);
231                         val   = (root_col == arg_col) ? 0.0 : 1.0;
232                         lpp_set_start_value(ienv->lp, y_idx, val);
233
234                         /* add constraints relating the affinity var to the color vars */
235                         for (col=0; col<n_colors; ++col) {
236                                 int cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_less_equal, 0.0);
237                                 int root_idx;
238                                 int arg_idx;
239
240                                 make_color_var_name(buf, sizeof(buf), root, col);
241                                 root_idx = lpp_get_var_idx(ienv->lp, buf);
242                                 make_color_var_name(buf, sizeof(buf), arg, col);
243                                 arg_idx  = lpp_get_var_idx(ienv->lp, buf);
244
245                                 lpp_set_factor_fast(ienv->lp, cst_idx, root_idx,  1.0);
246                                 lpp_set_factor_fast(ienv->lp, cst_idx, arg_idx,  -1.0);
247                                 lpp_set_factor_fast(ienv->lp, cst_idx, y_idx, -1.0);
248                         }
249                 }
250         }
251 }
252
253 /**
254  * Helping stuff for build_clique_star_cstr
255  */
256 typedef struct edge_t {
257         ir_node *n1;
258         ir_node *n2;
259 } edge_t;
260
261 static int compare_edge_t(const void *k1, const void *k2, size_t size)
262 {
263         const edge_t *e1 = k1;
264         const edge_t *e2 = k2;
265         (void) size;
266
267         return ! (e1->n1 == e2->n1 && e1->n2 == e2->n2);
268 }
269
270 #define HASH_EDGE(e) (hash_irn((e)->n1) ^ hash_irn((e)->n2))
271
272 static inline edge_t *add_edge(set *edges, ir_node *n1, ir_node *n2, size_t *counter)
273 {
274         edge_t new_edge;
275
276         if (PTR_TO_INT(n1) < PTR_TO_INT(n2)) {
277                 new_edge.n1 = n1;
278                 new_edge.n2 = n2;
279         } else {
280                 new_edge.n1 = n2;
281                 new_edge.n2 = n1;
282         }
283         (*counter)++;
284         return set_insert(edges, &new_edge, sizeof(new_edge), HASH_EDGE(&new_edge));
285 }
286
287 static inline edge_t *find_edge(set *edges, ir_node *n1, ir_node *n2)
288 {
289         edge_t new_edge;
290
291         if (PTR_TO_INT(n1) < PTR_TO_INT(n2)) {
292                 new_edge.n1 = n1;
293                 new_edge.n2 = n2;
294         } else {
295                 new_edge.n1 = n2;
296                 new_edge.n2 = n1;
297         }
298         return set_find(edges, &new_edge, sizeof(new_edge), HASH_EDGE(&new_edge));
299 }
300
301 static inline void remove_edge(set *edges, ir_node *n1, ir_node *n2, size_t *counter)
302 {
303         edge_t new_edge, *e;
304
305         if (PTR_TO_INT(n1) < PTR_TO_INT(n2)) {
306                 new_edge.n1 = n1;
307                 new_edge.n2 = n2;
308         } else {
309                 new_edge.n1 = n2;
310                 new_edge.n2 = n1;
311         }
312         e = set_find(edges, &new_edge, sizeof(new_edge), HASH_EDGE(&new_edge));
313         if (e) {
314                 e->n1 = NULL;
315                 e->n2 = NULL;
316                 (*counter)--;
317         }
318 }
319
320 #define pset_foreach(pset, irn)  for (irn=pset_first(pset); irn; irn=pset_next(pset))
321
322 /**
323  * Search for an interference clique and an external node
324  * with affinity edges to all nodes of the clique.
325  * At most 1 node of the clique can be colored equally with the external node.
326  */
327 static void build_clique_star_cstr(ilp_env_t *ienv)
328 {
329         affinity_node_t *aff;
330
331         /* for each node with affinity edges */
332         co_gs_foreach_aff_node(ienv->co, aff) {
333                 struct obstack ob;
334                 neighb_t *nbr;
335                 const ir_node *center = aff->irn;
336                 ir_node **nodes;
337                 set *edges;
338                 int i, o, n_nodes;
339                 size_t n_edges;
340
341                 if (arch_irn_is_ignore(aff->irn))
342                         continue;
343
344                 obstack_init(&ob);
345                 edges = new_set(compare_edge_t, 8);
346
347                 /* get all affinity neighbours */
348                 n_nodes = 0;
349                 co_gs_foreach_neighb(aff, nbr) {
350                         if (!arch_irn_is_ignore(nbr->irn)) {
351                                 obstack_ptr_grow(&ob, nbr->irn);
352                                 ++n_nodes;
353                         }
354                 }
355                 nodes = obstack_finish(&ob);
356
357                 /* get all interference edges between these */
358                 n_edges = 0;
359                 for (i=0; i<n_nodes; ++i) {
360                         for (o=0; o<i; ++o) {
361                                 if (be_ifg_connected(ienv->co->cenv->ifg, nodes[i], nodes[o]))
362                                         add_edge(edges, nodes[i], nodes[o], &n_edges);
363                         }
364                 }
365
366                 /* cover all these interference edges with maximal cliques */
367                 while (n_edges) {
368                         edge_t *e;
369                         pset   *clique = pset_new_ptr(8);
370                         bool    growed;
371
372                         /* get 2 starting nodes to form a clique */
373                         for (e=set_first(edges); !e->n1; e=set_next(edges)) {
374                         }
375
376                         /* we could be stepped out of the loop before the set iterated to the end */
377                         set_break(edges);
378
379                         pset_insert_ptr(clique, e->n1);
380                         pset_insert_ptr(clique, e->n2);
381                         remove_edge(edges, e->n1, e->n2, &n_edges);
382
383                         /* while the clique is growing */
384                         do {
385                                 growed = false;
386
387                                 /* search for a candidate to extend the clique */
388                                 for (i=0; i<n_nodes; ++i) {
389                                         ir_node *cand = nodes[i];
390                                         ir_node *member;
391                                         bool     is_cand;
392
393                                         /* if its already in the clique try the next */
394                                         if (pset_find_ptr(clique, cand))
395                                                 continue;
396
397                                         /* are there all necessary interferences? */
398                                         is_cand = true;
399                                         pset_foreach(clique, member) {
400                                                 if (!find_edge(edges, cand, member)) {
401                                                         is_cand = false;
402                                                         pset_break(clique);
403                                                         break;
404                                                 }
405                                         }
406
407                                         /* now we know if we have a clique extender */
408                                         if (is_cand) {
409                                                 /* first remove all covered edges */
410                                                 pset_foreach(clique, member)
411                                                         remove_edge(edges, cand, member, &n_edges);
412
413                                                 /* insert into clique */
414                                                 pset_insert_ptr(clique, cand);
415                                                 growed = true;
416                                                 break;
417                                         }
418                                 }
419                         } while (growed);
420
421                         /* now the clique is maximal. Finally add the constraint */
422                         {
423                                 ir_node *member;
424                                 int      var_idx;
425                                 int      cst_idx;
426                                 char     buf[32];
427
428                                 cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_greater_equal, pset_count(clique)-1);
429
430                                 pset_foreach(clique, member) {
431                                         make_affinity_var_name(buf, sizeof(buf), center, member);
432                                         var_idx = lpp_get_var_idx(ienv->lp, buf);
433                                         lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1.0);
434                                 }
435                         }
436
437                         del_pset(clique);
438                 }
439
440                 del_set(edges);
441                 obstack_free(&ob, NULL);
442         }
443 }
444
445 static void extend_path(ilp_env_t *ienv, pdeq *path, const ir_node *irn)
446 {
447         be_ifg_t *ifg = ienv->co->cenv->ifg;
448         int i, len;
449         ir_node **curr_path;
450         affinity_node_t *aff;
451         neighb_t *nbr;
452
453         /* do not walk backwards or in circles */
454         if (pdeq_contains(path, irn))
455                 return;
456
457         if (arch_irn_is_ignore(irn))
458                 return;
459
460         /* insert the new irn */
461         pdeq_putr(path, irn);
462
463         /* check for forbidden interferences */
464         len       = pdeq_len(path);
465         curr_path = ALLOCAN(ir_node*, len);
466         pdeq_copyl(path, (const void **)curr_path);
467
468         for (i=1; i<len; ++i) {
469                 if (be_ifg_connected(ifg, irn, curr_path[i]))
470                         goto end;
471         }
472
473         /* check for terminating interference */
474         if (be_ifg_connected(ifg, irn, curr_path[0])) {
475                 /* One node is not a path. */
476                 /* And a path of length 2 is covered by a clique star constraint. */
477                 if (len > 2) {
478                         /* finally build the constraint */
479                         int cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_greater_equal, 1.0);
480                         for (i=1; i<len; ++i) {
481                                 char buf[32];
482                                 int  var_idx;
483
484                                 make_affinity_var_name(buf, sizeof(buf), curr_path[i-1], curr_path[i]);
485                                 var_idx = lpp_get_var_idx(ienv->lp, buf);
486                                 lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1.0);
487                         }
488                 }
489
490                 /* this path cannot be extended anymore */
491                 goto end;
492         }
493
494         /* recursively extend the path */
495         aff = get_affinity_info(ienv->co, irn);
496         co_gs_foreach_neighb(aff, nbr) {
497                 extend_path(ienv, path, nbr->irn);
498         }
499
500 end:
501         /* remove the irn */
502         pdeq_getr(path);
503 }
504
505 /**
506  *  Search a path of affinity edges, whose ends are connected
507  *  by an interference edge and there are no other interference
508  *  edges in between.
509  *  Then at least one of these affinity edges must break.
510  */
511 static void build_path_cstr(ilp_env_t *ienv)
512 {
513         affinity_node_t *aff_info;
514
515         /* for each node with affinity edges */
516         co_gs_foreach_aff_node(ienv->co, aff_info) {
517                 pdeq *path = new_pdeq();
518
519                 extend_path(ienv, path, aff_info->irn);
520
521                 del_pdeq(path);
522         }
523 }
524
525 static void ilp2_build(ilp_env_t *ienv)
526 {
527         int lower_bound;
528
529         ienv->lp = lpp_new(ienv->co->name, lpp_minimize);
530         build_coloring_cstr(ienv);
531         build_interference_cstr(ienv);
532         build_affinity_cstr(ienv);
533         build_clique_star_cstr(ienv);
534         build_path_cstr(ienv);
535
536         lower_bound = co_get_lower_bound(ienv->co) - co_get_inevit_copy_costs(ienv->co);
537         lpp_set_bound(ienv->lp, lower_bound);
538 }
539
540 static void ilp2_apply(ilp_env_t *ienv)
541 {
542         local_env_t *lenv = ienv->env;
543         ir_graph    *irg  = ienv->co->irg;
544
545         /* first check if there was sth. to optimize */
546         if (lenv->first_x_var >= 0) {
547                 int              count = lenv->last_x_var - lenv->first_x_var + 1;
548                 double          *sol   = XMALLOCN(double, count);
549                 lpp_sol_state_t  state = lpp_get_solution(ienv->lp, sol, lenv->first_x_var, lenv->last_x_var);
550                 int              i;
551
552                 if (state != lpp_optimal) {
553                         printf("WARNING %s: Solution state is not 'optimal': %d\n",
554                                ienv->co->name, (int)state);
555                         if (state < lpp_feasible) {
556                                 panic("Copy coalescing solution not feasible!");
557                         }
558                 }
559
560                 for (i=0; i<count; ++i) {
561                         unsigned nodenr;
562                         unsigned color;
563                         char     var_name[32];
564                         if (sol[i] <= 1-EPSILON)
565                                 continue;
566                         /* split variable name into components */
567                         lpp_get_var_name(ienv->lp, lenv->first_x_var+i, var_name, sizeof(var_name));
568
569                         if (sscanf(var_name, "x_%u_%u", &nodenr, &color) == 2) {
570                                 ir_node *irn = get_idx_irn(irg, nodenr);
571                                 set_irn_col(ienv->co->cls, irn, color);
572                         } else {
573                                 panic("This should be a x-var");
574                         }
575                 }
576
577                 xfree(sol);
578         }
579
580 #ifdef COPYOPT_STAT
581         /* TODO adapt to multiple possible ILPs */
582         copystat_add_ilp_time((int)(1000.0*lpp_get_sol_time(pi->curr_lp)));  //now we have ms
583         copystat_add_ilp_vars(lpp_get_var_count(pi->curr_lp));
584         copystat_add_ilp_csts(lpp_get_cst_count(pi->curr_lp));
585         copystat_add_ilp_iter(lpp_get_iter_cnt(pi->curr_lp));
586 #endif
587 }
588
589 /**
590  * Solves the problem using mixed integer programming
591  * @returns 1 iff solution state was optimal
592  * Uses the OU and the GRAPH data structure
593  * Dependency of the OU structure can be removed
594  */
595 static int co_solve_ilp2(copy_opt_t *co)
596 {
597         unsigned        n_regs = arch_register_class_n_regs(co->cls);
598         lpp_sol_state_t sol_state;
599         ilp_env_t      *ienv;
600         local_env_t     my;
601
602         ASSERT_OU_AVAIL(co); //See build_clique_st
603         ASSERT_GS_AVAIL(co);
604
605         my.first_x_var = -1;
606         my.last_x_var  = -1;
607         FIRM_DBG_REGISTER(dbg, "firm.be.coilp2");
608
609         rbitset_alloca(my.normal_colors, n_regs);
610         be_set_allocatable_regs(co->irg, co->cls, my.normal_colors);
611         my.n_colors = rbitset_popcount(my.normal_colors, n_regs);
612
613         ienv = new_ilp_env(co, ilp2_build, ilp2_apply, &my);
614
615         sol_state = ilp_go(ienv);
616
617         free_ilp_env(ienv);
618
619         return sol_state == lpp_optimal;
620 }
621
622 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_copyilp2)
623 void be_init_copyilp2(void)
624 {
625         static co_algo_info copyheur = {
626                 co_solve_ilp2, 1
627         };
628
629         be_register_copyopt("ilp", &copyheur);
630 }