0b633dddaa94ed6123be4812bfcfebbf7309a25e
[libfirm] / ir / be / becopypbqp.c
1 /*
2  * becopypbqp.c
3  *
4  *  Created on: Aug 28, 2009
5  *      Author: bersch
6  */
7 #include "config.h"
8
9 #ifdef FIRM_KAPS
10
11 #include "kaps.h"
12 #include "pbqp_t.h"
13 #include "vector.h"
14 #include "matrix.h"
15 #include "html_dumper.h"
16 #include "heuristical.h"
17 #include "pbqp_node_t.h"
18
19 #include "becopyopt_t.h"
20 #include "beifg.h"
21 #include "beifg_t.h"
22 #include "irprintf_t.h"
23
24 #include "error.h"
25 #include "bitset.h"
26 #include "pmap.h"
27
28 static FILE *my_open(const be_chordal_env_t *env, const char *prefix, const char *suffix)
29 {
30         FILE *result;
31         char buf[1024];
32         size_t i, n;
33         char *tu_name;
34
35         n = strlen(env->birg->main_env->cup_name);
36         tu_name = XMALLOCN(char, n + 1);
37         strcpy(tu_name, env->birg->main_env->cup_name);
38         for (i = 0; i < n; ++i)
39                 if (tu_name[i] == '.')
40                         tu_name[i] = '_';
41
42         ir_snprintf(buf, sizeof(buf), "%s%s_%F_%s%s", prefix, tu_name, env->irg, env->cls->name, suffix);
43         xfree(tu_name);
44         result = fopen(buf, "wt");
45         if(result == NULL) {
46                 panic("Couldn't open '%s' for writing.", buf);
47         }
48
49         return result;
50 }
51
52 int co_solve_heuristic_pbqp(copy_opt_t *co) {
53         void *nodes_it  = be_ifg_nodes_iter_alloca(co->cenv->ifg);
54         void *neigh_it  = be_ifg_neighbours_iter_alloca(co->cenv->ifg);
55         ir_node *ifg_node, *if_neighb_node;
56
57         pbqp *pbqp_problem;
58         unsigned number_registers = co->cls->n_regs;
59         unsigned number_nodes = 0;
60         unsigned int nodeIdx = 0;
61
62         bitset_t *ignore_registers;
63         pmap *map;
64
65         // count nodes in ifg
66         be_ifg_foreach_node(co->cenv->ifg, nodes_it, ifg_node) {
67                 number_nodes++;
68         }
69
70         // create empty PBQP instance
71         pbqp_problem = alloc_pbqp(number_nodes);
72
73         //
74         ignore_registers = bitset_malloc(number_registers);
75         be_put_ignore_regs(co->cenv->birg, co->cls, ignore_registers);
76
77         // create map
78         map = pmap_create_ex(number_nodes);
79
80         // add costs vector to nodes
81         nodeIdx = 0;
82         be_ifg_foreach_node(co->cenv->ifg, nodes_it, ifg_node) {
83                 // create costs vector
84                 struct vector *costs_vector = vector_alloc(pbqp_problem, number_registers);
85
86                 // set costs
87                 unsigned int cnt;
88                 for(cnt = 0; cnt < costs_vector->len; cnt++) {
89                         if (bitset_is_set(ignore_registers,cnt)) {
90                                 vector_set(costs_vector, cnt, INF_COSTS);
91                         }
92                         else {
93                                 if (!arch_reg_out_is_allocatable(ifg_node, arch_register_for_index(co->cls, cnt)))
94                                 {
95                                         vector_set(costs_vector, cnt, INF_COSTS);
96                                 }
97                                 else {
98                                         vector_set(costs_vector, cnt, 0);
99                                 }
100                         }
101
102                         // add description
103                         vector_set_description(costs_vector, cnt, arch_register_for_index(co->cls, cnt)->name);
104                 }
105
106                 // add costs vector to node
107                 add_node_costs(pbqp_problem, nodeIdx, costs_vector);
108
109                 // insert ir_node and pbqp_node into map
110                 pmap_insert(map, ifg_node, get_node(pbqp_problem,nodeIdx));
111
112                 // increment nodeIndex
113                 nodeIdx++;
114         }
115
116         be_ifg_foreach_node(co->cenv->ifg, nodes_it, ifg_node) {
117                 pbqp_node *src_node = pmap_find(map,ifg_node)->value;
118                 unsigned int srcNodeIdx = src_node->index;
119
120                 // add costs matrix between nodes (interference edge)
121                 be_ifg_foreach_neighbour(co->cenv->ifg, neigh_it, ifg_node, if_neighb_node) {
122                         pbqp_node *trg_node = pmap_find(map,if_neighb_node)->value;
123                         if(get_edge(pbqp_problem, srcNodeIdx, trg_node->index) == NULL) {
124                                 // create costs matrix
125                                 struct pbqp_matrix *matrix = pbqp_matrix_alloc(pbqp_problem, number_registers, number_registers);
126
127                                 // set costs
128                                 unsigned row, col;
129                                 for(row = 0; row < number_registers; row++) {
130                                         for(col = 0; col < number_registers; col++) {
131                                                 if(row == col) {
132                                                         pbqp_matrix_set(matrix, row, col, INF_COSTS);
133                                                 }
134                                                 else {
135                                                         pbqp_matrix_set(matrix, row, col, 2);
136                                                 }
137                                         }
138                                 }
139
140                                 // add costs matrix to interference edge
141                                 add_edge_costs(pbqp_problem, srcNodeIdx, trg_node->index , matrix);
142                         }
143                 }
144
145                 // add costs matrix between nodes (affinety edge)
146                 affinity_node_t *aff_node = get_affinity_info(co, ifg_node);
147                 neighb_t *aff_neighb_node;
148                 if(aff_node != NULL) {
149                         co_gs_foreach_neighb(aff_node, aff_neighb_node) {
150                                 pbqp_node *trg_node = pmap_find(map,aff_neighb_node->irn)->value;
151                                 if(get_edge(pbqp_problem, srcNodeIdx, trg_node->index) == NULL) {
152                                         // create costs matrix
153                                         struct pbqp_matrix *matrix = pbqp_matrix_alloc(pbqp_problem, number_registers, number_registers);
154
155                                         // set costs
156                                         unsigned row, col;
157                                         for(row = 0; row < number_registers; row++) {
158                                                 for(col = 0; col < number_registers; col++) {
159                                                         if(row == col) {
160                                                                 pbqp_matrix_set(matrix, row, col, 0);
161                                                         }
162                                                         else {
163                                                                 pbqp_matrix_set(matrix, row, col, 2);
164                                                         }
165                                                 }
166                                         }
167
168                                         // add costs matrix to interference edge
169                                         add_edge_costs(pbqp_problem, srcNodeIdx, trg_node->index , matrix);
170                                 }
171                         }
172                 }
173         }
174
175 #if KAPS_DUMP
176         // dump graph before solving pbqp
177         FILE *file_before = my_open(co->cenv, "", "-before.html");
178         set_dumpfile(pbqp_problem, file_before);
179         pbqp_dump_input(pbqp_problem);
180 #endif
181
182
183         // solve pbqp problem
184         solve_pbqp_heuristical(pbqp_problem);
185         //solve_pbqp_brute_force(pbqp_problem);
186         num solution = get_solution(pbqp_problem);
187
188         assert(solution != INF_COSTS && "No PBQP solution found");
189
190         // printf("Solution (%s): %d\n",co->name, (int)solution);
191
192         // coloring ifg
193         be_ifg_foreach_node(co->cenv->ifg, nodes_it, ifg_node) {
194                 pbqp_node *node = pmap_find(map,ifg_node)->value;
195                 num index = get_node_solution(pbqp_problem, node->index);
196                 const arch_register_t *reg = arch_register_for_index(co->cls, index);
197                 arch_set_irn_register(ifg_node, reg);
198         }
199
200 #if KAPS_DUMP
201         // dump graph after solving pbqp
202         FILE *file_after = my_open(co->cenv, "", "-after.html");
203         set_dumpfile(pbqp_problem, file_after);
204         pbqp_dump_input(pbqp_problem);
205 #endif
206
207
208         // free pbqp resources
209 #if KAPS_DUMP
210         fclose(file_before);
211         fclose(file_after);
212 #endif
213         bitset_free(ignore_registers);
214         pmap_destroy(map);
215         free_pbqp(pbqp_problem);
216
217         return 0;
218 }
219
220 #endif