Fixed some whitespaces.
[libfirm] / ir / kaps / heuristical_co_ld.c
1 /*
2  * heuristical_co_ld.c
3  *
4  *  Created on: 06.05.2010
5  *      Author: berschth
6  */
7
8 #include "config.h"
9
10 #include "adt/array.h"
11 #include "assert.h"
12 #include "error.h"
13
14 #include "bucket.h"
15 #include "heuristical_co_ld.h"
16 #include "optimal.h"
17 #if KAPS_DUMP
18 #include "html_dumper.h"
19 #endif
20 #include "kaps.h"
21 #include "matrix.h"
22 #include "pbqp_edge.h"
23 #include "pbqp_edge_t.h"
24 #include "pbqp_node.h"
25 #include "pbqp_node_t.h"
26 #include "vector.h"
27
28 #include "plist.h"
29 #include "timing.h"
30
31 static void back_propagate_RI(pbqp_t *pbqp, pbqp_node_t *node)
32 {
33         pbqp_edge_t   *edge;
34         pbqp_node_t   *other;
35         pbqp_matrix_t *mat;
36         vector_t      *vec;
37         int            is_src;
38
39         edge = node->edges[0];
40         mat = edge->costs;
41         is_src = edge->src == node;
42         vec = node->costs;
43
44         if (is_src) {
45                 other = edge->tgt;
46                 node->solution = pbqp_matrix_get_col_min_index(mat, other->solution, vec);
47         } else {
48                 other = edge->src;
49                 node->solution = pbqp_matrix_get_row_min_index(mat, other->solution, vec);
50         }
51
52 #if KAPS_DUMP
53         if (pbqp->dump_file) {
54                 fprintf(pbqp->dump_file, "node n%d is set to %d<br>\n", node->index, node->solution);
55         }
56 #endif
57 }
58
59 static void back_propagate_RII(pbqp_t *pbqp, pbqp_node_t *node)
60 {
61         pbqp_edge_t   *src_edge   = node->edges[0];
62         pbqp_edge_t   *tgt_edge   = node->edges[1];
63         int            src_is_src = src_edge->src == node;
64         int            tgt_is_src = tgt_edge->src == node;
65         pbqp_matrix_t *src_mat;
66         pbqp_matrix_t *tgt_mat;
67         pbqp_node_t   *src_node;
68         pbqp_node_t   *tgt_node;
69         vector_t      *vec;
70         vector_t      *node_vec;
71         unsigned       col_index;
72         unsigned       row_index;
73
74         assert(pbqp);
75
76         if (src_is_src) {
77                 src_node = src_edge->tgt;
78         } else {
79                 src_node = src_edge->src;
80         }
81
82         if (tgt_is_src) {
83                 tgt_node = tgt_edge->tgt;
84         } else {
85                 tgt_node = tgt_edge->src;
86         }
87
88         /* Swap nodes if necessary. */
89         if (tgt_node->index < src_node->index) {
90                 pbqp_node_t *tmp_node;
91                 pbqp_edge_t *tmp_edge;
92
93                 tmp_node = src_node;
94                 src_node = tgt_node;
95                 tgt_node = tmp_node;
96
97                 tmp_edge = src_edge;
98                 src_edge = tgt_edge;
99                 tgt_edge = tmp_edge;
100
101                 src_is_src = src_edge->src == node;
102                 tgt_is_src = tgt_edge->src == node;
103         }
104
105         src_mat = src_edge->costs;
106         tgt_mat = tgt_edge->costs;
107
108         node_vec = node->costs;
109
110         row_index = src_node->solution;
111         col_index = tgt_node->solution;
112
113         vec = vector_copy(pbqp, node_vec);
114
115         if (src_is_src) {
116                 vector_add_matrix_col(vec, src_mat, row_index);
117         } else {
118                 vector_add_matrix_row(vec, src_mat, row_index);
119         }
120
121         if (tgt_is_src) {
122                 vector_add_matrix_col(vec, tgt_mat, col_index);
123         } else {
124                 vector_add_matrix_row(vec, tgt_mat, col_index);
125         }
126
127         node->solution = vector_get_min_index(vec);
128
129 #if KAPS_DUMP
130         if (pbqp->dump_file) {
131                 fprintf(pbqp->dump_file, "node n%d is set to %d<br>\n", node->index, node->solution);
132         }
133 #endif
134
135         obstack_free(&pbqp->obstack, vec);
136 }
137
138 static void back_propagate_RN(pbqp_t *pbqp, pbqp_node_t *node)
139 {
140         vector_t    *vec        = NULL;
141         pbqp_node_t *neighbor   = NULL;
142         pbqp_edge_t *edge       = NULL;
143         unsigned     edge_index = 0;
144
145         assert(pbqp);
146
147         vec = vector_copy(pbqp, node->costs);
148
149         for(edge_index = 0; edge_index < pbqp_node_get_degree(node); edge_index++) {
150                 /* get neighbor node */
151                 edge = node->edges[edge_index];
152                 neighbor = edge->src == node ? edge->tgt : edge->src;
153
154                 /* node is edge src node */
155                 if(edge->src == node)
156                         vector_add_matrix_col(vec, edge->costs, neighbor->solution);
157                 /* node is edge tgt node */
158                 else
159                         vector_add_matrix_row(vec, edge->costs, neighbor->solution);
160         }
161
162         assert(vector_get_min(vec) != INF_COSTS);
163         node->solution = vector_get_min_index(vec);
164
165 #if KAPS_DUMP
166         if (pbqp->dump_file) {
167                 fprintf(pbqp->dump_file, "node n%d is set to %d<br>\n", node->index, node->solution);
168         }
169 #endif
170
171         obstack_free(&pbqp->obstack, vec);
172 }
173
174 static void back_propagate_ld(pbqp_t *pbqp)
175 {
176         unsigned node_index;
177         unsigned node_len   = node_bucket_get_length(reduced_bucket);
178
179         assert(pbqp);
180
181 #if KAPS_DUMP
182         if (pbqp->dump_file) {
183                 dump_section(pbqp->dump_file, 2, "Back Propagation");
184         }
185 #endif
186
187         for (node_index = node_len; node_index > 0; --node_index) {
188                 pbqp_node_t *node = reduced_bucket[node_index - 1];
189
190                 switch (pbqp_node_get_degree(node)) {
191                         case 1:
192                                 back_propagate_RI(pbqp, node);
193                                 break;
194                         case 2:
195                                 back_propagate_RII(pbqp, node);
196                                 break;
197                         default:
198                                 back_propagate_RN(pbqp, node);
199                                 break;
200                 }
201         }
202 }
203
204 static void merge_into_RN_node(pbqp_t *pbqp, plist_t *rpeo)
205 {
206         pbqp_node_t *node = NULL;
207
208         assert(pbqp);
209
210         do {
211                 /* get last element from reverse perfect elimination order */
212                 node = (pbqp_node_t*)plist_last(rpeo)->data;
213                 /* remove element from reverse perfect elimination order */
214                 plist_erase(rpeo, plist_last(rpeo));
215                 /* insert node at the beginning of rpeo so the rpeo already exits after pbqp solving */
216                 plist_insert_front(rpeo, node);
217         } while(node_is_reduced(node));
218
219         assert(pbqp_node_get_degree(node) > 2);
220
221         /* Check whether we can merge a neighbor into the current node. */
222         apply_RM(pbqp, node);
223 }
224
225 static void apply_RN_co_without_selection(pbqp_t *pbqp)
226 {
227         pbqp_node_t *node;
228         unsigned     edge_index;
229
230         assert(pbqp);
231
232         node        = merged_node;
233         merged_node = NULL;
234
235         if (node_is_reduced(node))
236                 return;
237
238 #if KAPS_DUMP
239         if (pbqp->dump_file) {
240                 char     txt[100];
241                 sprintf(txt, "RN-Reduction of Node n%d", node->index);
242                 dump_section(pbqp->dump_file, 2, txt);
243                 pbqp_dump_graph(pbqp);
244         }
245 #endif
246
247         /* Disconnect neighbor nodes */
248         for(edge_index = 0; edge_index < pbqp_node_get_degree(node); edge_index++) {
249                 pbqp_edge_t *edge;
250                 pbqp_node_t *neighbor;
251
252                 /* get neighbor node */
253                 edge = node->edges[edge_index];
254
255                 neighbor = edge->src == node ? edge->tgt : edge->src;
256
257                 assert(neighbor != node);
258
259                 if(!is_connected(neighbor, edge))
260                         continue;
261
262                 disconnect_edge(neighbor, edge);
263                 reorder_node_after_edge_deletion(neighbor);
264         }
265
266         /* Remove node from old bucket */
267         node_bucket_remove(&node_buckets[3], node);
268
269         /* Add node to back propagation list. */
270         node_bucket_insert(&reduced_bucket, node);
271 }
272
273 static void apply_heuristic_reductions_co(pbqp_t *pbqp, plist_t *rpeo)
274 {
275         #if KAPS_TIMING
276                 /* create timers */
277                 ir_timer_t *t_edge = ir_timer_new();
278                 ir_timer_t *t_r1   = ir_timer_new();
279                 ir_timer_t *t_r2   = ir_timer_new();
280                 ir_timer_t *t_rn   = ir_timer_new();
281         #endif
282
283         for (;;) {
284                 if (edge_bucket_get_length(edge_bucket) > 0) {
285                         #if KAPS_TIMING
286                                 ir_timer_start(t_edge);
287                         #endif
288
289                         apply_edge(pbqp);
290
291                         #if KAPS_TIMING
292                                 ir_timer_stop(t_edge);
293                         #endif
294                 } else if (node_bucket_get_length(node_buckets[1]) > 0) {
295                         #if KAPS_TIMING
296                                 ir_timer_start(t_r1);
297                         #endif
298
299                         apply_RI(pbqp);
300
301                         #if KAPS_TIMING
302                                 ir_timer_stop(t_r1);
303                         #endif
304                 } else if (node_bucket_get_length(node_buckets[2]) > 0) {
305                         #if KAPS_TIMING
306                                 ir_timer_start(t_r2);
307                         #endif
308
309                         apply_RII(pbqp);
310
311                         #if KAPS_TIMING
312                                 ir_timer_stop(t_r2);
313                         #endif
314                 } else if (merged_node != NULL) {
315                         #if KAPS_TIMING
316                                 ir_timer_start(t_rn);
317                         #endif
318
319                         apply_RN_co_without_selection(pbqp);
320
321                         #if KAPS_TIMING
322                                 ir_timer_stop(t_rn);
323                         #endif
324                 } else if (node_bucket_get_length(node_buckets[3]) > 0) {
325                         #if KAPS_TIMING
326                                 ir_timer_start(t_rn);
327                         #endif
328
329                         merge_into_RN_node(pbqp, rpeo);
330
331                         #if KAPS_TIMING
332                                 ir_timer_stop(t_rn);
333                         #endif
334                 } else {
335                         #if KAPS_TIMING
336                                 printf("PBQP RE reductions:           %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_edge) / 1000.0);
337                                 printf("PBQP R1 reductions:           %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_r1) / 1000.0);
338                                 printf("PBQP R2 reductions:           %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_r2) / 1000.0);
339                                 printf("PBQP RN reductions:           %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_rn) / 1000.0);
340                         #endif
341
342                         return;
343                 }
344         }
345 }
346
347 void solve_pbqp_heuristical_co_ld(pbqp_t *pbqp, plist_t *rpeo)
348 {
349         /* Reduce nodes degree ... */
350         initial_simplify_edges(pbqp);
351
352         /* ... and put node into bucket representing their degree. */
353         fill_node_buckets(pbqp);
354
355         #if KAPS_STATISTIC
356                 FILE *fh = fopen("solutions.pb", "a");
357                 fprintf(fh, "Solution");
358                 fclose(fh);
359         #endif
360
361         apply_heuristic_reductions_co(pbqp, rpeo);
362
363         pbqp->solution = determine_solution(pbqp);
364
365         #if KAPS_STATISTIC
366                 fh = fopen("solutions.pb", "a");
367                 #if KAPS_USE_UNSIGNED
368                         fprintf(fh, ": %u RE:%u R0:%u R1:%u R2:%u RM:%u RN/BF:%u\n", pbqp->solution,
369                                         pbqp->num_edges, pbqp->num_r0, pbqp->num_r1, pbqp->num_r2,
370                                         pbqp->num_rm, pbqp->num_rn);
371                 #else
372                         fprintf(fh, ": %lld RE:%u R0:%u R1:%u R2:%u RM:%u RN/BF:%u\n", pbqp->solution,
373                                         pbqp->num_edges, pbqp->num_r0, pbqp->num_r1, pbqp->num_r2,
374                                         pbqp->num_rm, pbqp->num_rn);
375                 #endif
376                 fclose(fh);
377         #endif
378
379         /* Solve reduced nodes. */
380         back_propagate_ld(pbqp);
381
382         free_buckets();
383 }