- Normalized some more testapps
[libfirm] / ir / be / beifg.c
1 /**
2  * @file   beifg.c
3  * @date   18.11.2005
4  * @author Sebastian Hack
5  *
6  * Copyright (C) 2005 Universitaet Karlsruhe
7  * Released under the GPL
8  */
9
10 #include <stdlib.h>
11
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15
16 #ifdef HAVE_MALLOC_H
17 #include <malloc.h>
18 #endif
19
20 #ifdef __linux__
21 #include <malloc.h>
22 #endif /* __linux__ */
23
24 #ifdef HAVE_ALLOCA_H
25 #include <alloca.h>
26 #endif
27
28 #ifdef WITH_LIBCORE
29 #include <libcore/lc_opts.h>
30 #include <libcore/lc_opts_enum.h>
31 #include <libcore/lc_timing.h>
32 #endif /* WITH_LIBCORE */
33
34 #include "bitset.h"
35
36 #include "irgwalk.h"
37 #include "irnode_t.h"
38 #include "irprintf.h"
39 #include "irtools.h"
40 #include "beifg_t.h"
41 #include "beifg_impl.h"
42 #include "irphase.h"
43 #include "irphase_t.h"
44 #include "bechordal.h"
45
46 #include "becopystat.h"
47 #include "becopyopt.h"
48
49 /** Defines values for the ifg performance test */
50 #define BE_CH_PERFORMANCETEST_MIN_NODES (50)
51 #define BE_CH_PERFORMANCETEST_COUNT (500)
52
53 typedef struct _coloring_t coloring_t;
54
55 struct _coloring_t {
56         phase_t ph;
57         const arch_env_t *arch_env;
58         ir_graph *irg;
59 };
60
61 size_t (be_ifg_nodes_iter_size)(const void *self)
62 {
63         const be_ifg_t *ifg = self;
64         return ifg->impl->nodes_iter_size;
65 }
66
67 size_t (be_ifg_neighbours_iter_size)(const void *self)
68 {
69         const be_ifg_t *ifg = self;
70         return ifg->impl->neighbours_iter_size;
71 }
72
73 size_t (be_ifg_cliques_iter_size)(const void *self)
74 {
75         const be_ifg_t *ifg = self;
76         return ifg->impl->cliques_iter_size;
77 }
78
79 static void *regs_irn_data_init(phase_t *ph, ir_node *irn, void *data)
80 {
81         coloring_t *coloring = (coloring_t *) ph;
82         return (void *) arch_get_irn_register(coloring->arch_env, irn);
83 }
84
85 coloring_t *coloring_init(coloring_t *c, ir_graph *irg, const arch_env_t *aenv)
86 {
87         phase_init(&c->ph, "regs_map", irg, PHASE_DEFAULT_GROWTH, regs_irn_data_init);
88         c->arch_env = aenv;
89         c->irg = irg;
90         return c;
91 }
92
93 static void get_irn_color(ir_node *irn, void *c)
94 {
95         coloring_t *coloring = c;
96         phase_get_or_set_irn_data(&coloring->ph, irn);
97 }
98
99 static void restore_irn_color(ir_node *irn, void *c)
100 {
101         coloring_t *coloring = c;
102         const arch_register_t *reg = phase_get_irn_data(&coloring->ph, irn);
103         if(reg)
104                 arch_set_irn_register(coloring->arch_env, irn, reg);
105 }
106
107 void coloring_save(coloring_t *c)
108 {
109         irg_walk_graph(c->irg, NULL, get_irn_color, c);
110 }
111
112 void coloring_restore(coloring_t *c)
113 {
114         irg_walk_graph(c->irg, NULL, restore_irn_color, c);
115 }
116
117 void (be_ifg_free)(void *self)
118 {
119         be_ifg_t *ifg = self;
120         ifg->impl->free(self);
121 }
122
123 int (be_ifg_connected)(const void *self, const ir_node *a, const ir_node *b)
124 {
125         const be_ifg_t *ifg = self;
126         return ifg->impl->connected(self, a, b);
127 }
128
129 ir_node *(be_ifg_neighbours_begin)(const void *self, void *iter, const ir_node *irn)
130 {
131         const be_ifg_t *ifg = self;
132         return ifg->impl->neighbours_begin(self, iter, irn);
133 }
134
135 ir_node *(be_ifg_neighbours_next)(const void *self, void *iter)
136 {
137         const be_ifg_t *ifg = self;
138         return ifg->impl->neighbours_next(self, iter);
139 }
140
141 void (be_ifg_neighbours_break)(const void *self, void *iter)
142 {
143         const be_ifg_t *ifg = self;
144         ifg->impl->neighbours_break(self, iter);
145 }
146
147 ir_node *(be_ifg_nodes_begin)(const void *self, void *iter)
148 {
149         const be_ifg_t *ifg = self;
150         return ifg->impl->nodes_begin(self, iter);
151 }
152
153 ir_node *(be_ifg_nodes_next)(const void *self, void *iter)
154 {
155         const be_ifg_t *ifg = self;
156         return ifg->impl->nodes_next(self, iter);
157 }
158
159 void (be_ifg_nodes_break)(const void *self, void *iter)
160 {
161         const be_ifg_t *ifg = self;
162         ifg->impl->nodes_break(self, iter);
163 }
164
165 int (be_ifg_cliques_begin)(const void *self, void *iter, ir_node **buf)
166 {
167         const be_ifg_t *ifg = self;
168         return ifg->impl->cliques_begin(self, iter, buf);
169 }
170
171 int (be_ifg_cliques_next)(const void *self, void *iter)
172 {
173         const be_ifg_t *ifg = self;
174         return ifg->impl->cliques_next(self, iter);
175 }
176
177 void (be_ifg_cliques_break)(const void *self, void *iter)
178 {
179         const be_ifg_t *ifg = self;
180         ifg->impl->cliques_break(self, iter);
181 }
182
183 int (be_ifg_degree)(const void *self, const ir_node *irn)
184 {
185         const be_ifg_t *ifg = self;
186         return ifg->impl->degree(self, irn);
187 }
188
189
190 int be_ifg_is_simplicial(const be_ifg_t *ifg, const ir_node *irn)
191 {
192         int degree = be_ifg_degree(ifg, irn);
193         void *iter = be_ifg_neighbours_iter_alloca(ifg);
194
195         ir_node **neighbours = xmalloc(degree * sizeof(neighbours[0]));
196
197         ir_node *curr;
198         int i, j;
199
200         i = 0;
201         be_ifg_foreach_neighbour(ifg, iter, irn, curr)
202                 neighbours[i++] = curr;
203
204         for(i = 0; i < degree; ++i) {
205                 for(j = 0; j < i; ++j)
206                         if(!be_ifg_connected(ifg, neighbours[i], neighbours[j])) {
207                                 free(neighbours);
208                                 return 0;
209                         }
210         }
211
212
213         free(neighbours);
214         return 1;
215 }
216
217 void be_ifg_check(const be_ifg_t *ifg)
218 {
219         void *iter1 = be_ifg_nodes_iter_alloca(ifg);
220         void *iter2 = be_ifg_neighbours_iter_alloca(ifg);
221
222         ir_node *n, *m;
223         int node_count = 0;
224         int neighbours_count = 0;
225         int degree = 0;
226
227         /* count all nodes */
228         ir_printf("\n\nFound the following nodes in the graph %+F:\n\n", current_ir_graph);
229         be_ifg_foreach_node(ifg,iter1,n)
230         {
231                 node_count++;
232                 degree = be_ifg_degree(ifg, n);
233                 ir_printf("%d. %+F with degree: %d\n", node_count, n, degree);
234         }
235
236         ir_printf("\n\nNumber of nodes: %d\n\n", node_count);
237
238         /* Check, if all neighbours are indeed connected to the node. */
239         be_ifg_foreach_node(ifg, iter1, n)
240         {
241                 ir_printf("\n%+F; ", n);
242                 be_ifg_foreach_neighbour(ifg, iter2, n, m)
243                 {
244                         ir_printf("%+F; ", m);
245                         neighbours_count++;
246                         if(!be_ifg_connected(ifg, n, m))
247                                 ir_fprintf(stderr, "%+F is a neighbour of %+F but they are not connected!\n", n, m);
248                 }
249         }
250         ir_printf("\n\nFound %d nodes in the 'check neighbour section'\n", neighbours_count);
251 }
252
253 int be_ifg_check_get_node_count(const be_ifg_t *ifg)
254 {
255         void *iter = be_ifg_nodes_iter_alloca(ifg);
256         int node_count = 0;
257         ir_node *n;
258
259         be_ifg_foreach_node(ifg, iter, n)
260         {
261                 node_count++;
262         }
263
264         return node_count;
265 }
266
267 static int be_ifg_check_cmp_nodes(const void *a, const void *b)
268 {
269         const ir_node *node_a = *(ir_node **)a;
270         const ir_node *node_b = *(ir_node **)b;
271
272         int nr_a = node_a->node_nr;
273         int nr_b = node_b->node_nr;
274
275         return QSORT_CMP(nr_a, nr_b);
276 }
277
278 void be_ifg_check_sorted(const be_ifg_t *ifg)
279 {
280         void *iter1 = be_ifg_nodes_iter_alloca(ifg);
281         void *iter2 = be_ifg_neighbours_iter_alloca(ifg);
282
283         ir_node *n, *m;
284         const int node_count = be_ifg_check_get_node_count(ifg);
285         int neighbours_count = 0;
286         int i = 0;
287
288         ir_node **all_nodes = xmalloc(node_count * sizeof(all_nodes[0]));
289
290         be_ifg_foreach_node(ifg, iter1, n)
291         {
292                 if(!node_is_in_irgs_storage(ifg->env->irg, n))
293                 {
294                         printf ("+%F is in ifg but not in the current irg!",n);
295                         assert (node_is_in_irgs_storage(ifg->env->irg, n));
296                 }
297
298                 all_nodes[i] = n;
299                 i++;
300         }
301
302         qsort(all_nodes, node_count, sizeof(all_nodes[0]), be_ifg_check_cmp_nodes);
303
304         for (i = 0; i < node_count; i++)
305         {
306                 ir_node **neighbours = xmalloc(node_count * sizeof(neighbours[0]));
307                 int j = 0;
308                 int k = 0;
309                 int degree = 0;
310
311                 degree = be_ifg_degree(ifg, all_nodes[i]);
312
313                 be_ifg_foreach_neighbour(ifg, iter2, all_nodes[i], m)
314                 {
315                         neighbours[j] = m;
316                         j++;
317                 }
318
319                 qsort(neighbours, j, sizeof(neighbours[0]), be_ifg_check_cmp_nodes);
320
321                 ir_printf("%d. %+F's neighbours(%d): ", i+1, all_nodes[i], degree);
322
323                 for(k = 0; k < j; k++)
324                 {
325                         ir_printf("%+F, ", neighbours[k]);
326                 }
327
328                 ir_printf("\n");
329
330                 free(neighbours);
331         }
332
333         free(all_nodes);
334
335 }
336
337 void be_ifg_check_sorted_to_file(const be_ifg_t *ifg, FILE *f)
338 {
339         void *iter1 = be_ifg_nodes_iter_alloca(ifg);
340         void *iter2 = be_ifg_neighbours_iter_alloca(ifg);
341
342         ir_node *n, *m;
343         const int node_count = be_ifg_check_get_node_count(ifg);
344         int neighbours_count = 0;
345         int i = 0;
346
347         ir_node **all_nodes = xmalloc(node_count * sizeof(all_nodes[0]));
348
349         be_ifg_foreach_node(ifg, iter1, n)
350         {
351                 if(!node_is_in_irgs_storage(ifg->env->irg, n))
352                 {
353                         ir_fprintf (f,"+%F is in ifg but not in the current irg!",n);
354                         assert (node_is_in_irgs_storage(ifg->env->irg, n));
355                 }
356
357                 all_nodes[i] = n;
358                 i++;
359         }
360
361         qsort(all_nodes, node_count, sizeof(all_nodes[0]), be_ifg_check_cmp_nodes);
362
363         for (i = 0; i < node_count; i++)
364         {
365                 ir_node **neighbours = xmalloc(node_count * sizeof(neighbours[0]));
366                 int j = 0;
367                 int k = 0;
368                 int degree = 0;
369
370                 degree = be_ifg_degree(ifg, all_nodes[i]);
371
372                 be_ifg_foreach_neighbour(ifg, iter2, all_nodes[i], m)
373                 {
374                         neighbours[j] = m;
375                         j++;
376                 }
377
378                 qsort(neighbours, j, sizeof(neighbours[0]), be_ifg_check_cmp_nodes);
379
380                 ir_fprintf (f,"%d. %+F's neighbours(%d): ", i+1, all_nodes[i], degree);
381
382                 for(k = 0; k < j; k++)
383                 {
384                         ir_fprintf (f,"%+F, ", neighbours[k]);
385                 }
386
387                 ir_fprintf (f,"\n");
388
389                 free(neighbours);
390         }
391
392         free(all_nodes);
393
394 }
395
396 void be_ifg_check_performance(be_chordal_env_t *chordal_env)
397 {
398         int tests = BE_CH_PERFORMANCETEST_COUNT;
399         coloring_t coloring;
400
401         int used_memory;
402
403         int i = 0;
404         int rt;
405         copy_opt_t *co;
406         be_ifg_t *old_if = chordal_env->ifg;
407
408         lc_timer_t *timer = lc_timer_register("getTime","get Time of copy minimization using the ifg");
409         unsigned long elapsed_usec = 0;
410
411         if ((int) get_irg_estimated_node_cnt >= BE_CH_PERFORMANCETEST_MIN_NODES)
412         {
413                 coloring_init(&coloring, chordal_env->irg, chordal_env->birg->main_env->arch_env);
414                 coloring_save(&coloring);
415
416                 lc_timer_reset(timer);
417
418                 for (i = 0; i<tests; i++) /* performance test with std */
419                 {
420
421                         used_memory = lc_get_heap_used_bytes();
422
423                         rt = lc_timer_enter_high_priority();
424                         lc_timer_start(timer);
425
426                         chordal_env->ifg = be_ifg_std_new(chordal_env);
427
428                         lc_timer_stop(timer);
429                         rt = lc_timer_leave_high_priority();
430
431                         used_memory = lc_get_heap_used_bytes() - used_memory;
432
433                         coloring_restore(&coloring);
434
435                         co = NULL;
436                         co = new_copy_opt(chordal_env, co_get_costs_loop_depth);
437                         co_build_ou_structure(co);
438                         co_build_graph_structure(co);
439
440                         rt = lc_timer_enter_high_priority();
441                         lc_timer_start(timer);
442
443                         co_solve_heuristic_new(co);
444
445                         lc_timer_stop(timer);
446                         rt = lc_timer_leave_high_priority();
447
448                         co_free_graph_structure(co);
449                         co_free_ou_structure(co);
450                         free_copy_opt(co);
451                         be_ifg_free(chordal_env->ifg);
452
453                 }
454
455                 elapsed_usec = lc_timer_elapsed_usec(timer);
456                 /* calculating average */
457                 elapsed_usec = elapsed_usec / tests;
458
459                 ir_printf("\nstd:; %+F; %u; %u ",current_ir_graph, used_memory, elapsed_usec);
460
461                 i=0;
462                 used_memory=0;
463                 elapsed_usec=0;
464
465                 for (i = 0; i<tests; i++)  /* performance test with clique */
466                 {
467                         used_memory = lc_get_heap_used_bytes();
468
469                         rt = lc_timer_enter_high_priority();
470                         lc_timer_start(timer);
471
472                         chordal_env->ifg = be_ifg_clique_new(chordal_env);
473
474                         lc_timer_stop(timer);
475                         rt = lc_timer_leave_high_priority();
476
477                         used_memory = lc_get_heap_used_bytes() - used_memory;
478
479                         coloring_restore(&coloring);
480
481                         co = NULL;
482                         co = new_copy_opt(chordal_env, co_get_costs_loop_depth);
483                         co_build_ou_structure(co);
484                         co_build_graph_structure(co);
485
486                         rt = lc_timer_enter_high_priority();
487                         lc_timer_start(timer);
488
489                         co_solve_heuristic_new(co);
490
491                         lc_timer_stop(timer);
492                         rt = lc_timer_leave_high_priority();
493
494                         co_free_graph_structure(co);
495                         co_free_ou_structure(co);
496                         free_copy_opt(co);
497                         be_ifg_free(chordal_env->ifg);
498
499                 }
500
501                 elapsed_usec = lc_timer_elapsed_usec(timer);
502                 /* calculating average */
503                 elapsed_usec = elapsed_usec / tests;
504
505                 ir_printf("\nclique:; %+F; %u; %u ",current_ir_graph, used_memory, elapsed_usec);
506
507                 i=0;
508                 used_memory=0;
509                 elapsed_usec=0;
510
511                 for (i = 0; i<tests; i++)  /* performance test with list */
512                 {
513                         used_memory = lc_get_heap_used_bytes();
514
515                         rt = lc_timer_enter_high_priority();
516                         lc_timer_start(timer);
517
518                         chordal_env->ifg = be_ifg_list_new(chordal_env);
519
520                         lc_timer_stop(timer);
521                         rt = lc_timer_leave_high_priority();
522
523                         used_memory = lc_get_heap_used_bytes() - used_memory;
524
525                         coloring_restore(&coloring);
526
527                         co = NULL;
528                         co = new_copy_opt(chordal_env, co_get_costs_loop_depth);
529                         co_build_ou_structure(co);
530                         co_build_graph_structure(co);
531
532                         rt = lc_timer_enter_high_priority();
533                         lc_timer_start(timer);
534
535                         co_solve_heuristic_new(co);
536
537                         lc_timer_stop(timer);
538                         rt = lc_timer_leave_high_priority();
539
540                         co_free_graph_structure(co);
541                         co_free_ou_structure(co);
542                         free_copy_opt(co);
543                         be_ifg_free(chordal_env->ifg);
544
545                 }
546
547                 elapsed_usec = lc_timer_elapsed_usec(timer);
548                 /* calculating average */
549                 elapsed_usec = elapsed_usec / tests;
550
551                 ir_printf("\nlist:; %+F; %u; %u ",current_ir_graph, used_memory, elapsed_usec);
552
553                 i=0;
554                 used_memory=0;
555                 elapsed_usec=0;
556
557                 for (i = 0; i<tests; i++)  /* performance test with pointer */
558                 {
559                         used_memory = lc_get_heap_used_bytes();
560
561                         rt = lc_timer_enter_high_priority();
562                         lc_timer_start(timer);
563
564                         chordal_env->ifg = be_ifg_pointer_new(chordal_env);
565
566                         lc_timer_stop(timer);
567                         rt = lc_timer_leave_high_priority();
568
569                         used_memory = lc_get_heap_used_bytes() - used_memory;
570
571                         coloring_restore(&coloring);
572
573                         co = NULL;
574                         co = new_copy_opt(chordal_env, co_get_costs_loop_depth);
575                         co_build_ou_structure(co);
576                         co_build_graph_structure(co);
577
578                         rt = lc_timer_enter_high_priority();
579                         lc_timer_start(timer);
580
581                         co_solve_heuristic_new(co);
582
583                         lc_timer_stop(timer);
584                         rt = lc_timer_leave_high_priority();
585
586                         co_free_graph_structure(co);
587                         co_free_ou_structure(co);
588                         free_copy_opt(co);
589                         be_ifg_free(chordal_env->ifg);
590
591                 }
592
593                 elapsed_usec = lc_timer_elapsed_usec(timer);
594                 /* calculating average */
595                 elapsed_usec = elapsed_usec / tests;
596
597                 ir_printf("\npointer:; %+F; %u; %u ",current_ir_graph, used_memory, elapsed_usec);
598
599                 i=0;
600                 used_memory=0;
601                 elapsed_usec=0;
602         }
603
604         chordal_env->ifg = old_if;
605 }
606
607 void be_ifg_dump_dot(be_ifg_t *ifg, ir_graph *irg, FILE *file, const be_ifg_dump_dot_cb_t *cb, void *self)
608 {
609         void *nodes_it  = be_ifg_nodes_iter_alloca(ifg);
610         void *neigh_it  = be_ifg_neighbours_iter_alloca(ifg);
611         bitset_t *nodes = bitset_malloc(get_irg_last_idx(irg));
612
613         ir_node *n, *m;
614
615         fprintf(file, "graph G {\n\tgraph [");
616         if(cb->graph_attr)
617                 cb->graph_attr(file, self);
618         fprintf(file, "];\n");
619
620         if(cb->at_begin)
621                 cb->at_begin(file, self);
622
623         be_ifg_foreach_node(ifg, nodes_it, n) {
624                 if(cb->is_dump_node && cb->is_dump_node(self, n)) {
625                         int idx = get_irn_idx(n);
626                         bitset_set(nodes, idx);
627                         fprintf(file, "\tnode [");
628                         if(cb->node_attr)
629                                 cb->node_attr(file, self, n);
630                         fprintf(file, "]; n%d;\n", idx);
631                 }
632         }
633
634         /* Check, if all neighbours are indeed connected to the node. */
635         be_ifg_foreach_node(ifg, nodes_it, n) {
636                 be_ifg_foreach_neighbour(ifg, neigh_it, n, m) {
637                         int n_idx = get_irn_idx(n);
638                         int m_idx = get_irn_idx(m);
639
640                         if(n_idx < m_idx && bitset_is_set(nodes, n_idx) && bitset_is_set(nodes, m_idx)) {
641                                 fprintf(file, "\tn%d -- n%d [", n_idx, m_idx);
642                                 if(cb->edge_attr)
643                                         cb->edge_attr(file, self, n, m);
644                                 fprintf(file, "];\n");
645                         }
646                 }
647         }
648
649         if(cb->at_end)
650                 cb->at_end(file, self);
651
652         fprintf(file, "}\n");
653         bitset_free(nodes);
654 }