beifg: Factorise code to count interference components.
[libfirm] / ir / be / bedump.c
1 /*
2  * This file is part of libFirm.
3  * Copyright (C) 2012 University of Karlsruhe.
4  */
5
6 /**
7  * @file
8  * @brief       Code for dumping backend datastructures (i.e. interference graphs)
9  * @author      Matthias Braun
10  */
11 #include "config.h"
12
13 #include "bedump.h"
14
15 #include "irdump_t.h"
16 #include "irgwalk.h"
17 #include "beifg.h"
18 #include "becopyopt_t.h"
19 #include "belive_t.h"
20
21 static void dump_ifg_nodes(FILE *F, const be_ifg_t *ifg)
22 {
23         be_ifg_foreach_node(ifg, node) {
24                 dump_node(F, node);
25         }
26 }
27
28 static void dump_ifg_edges(FILE *F, const be_ifg_t *ifg)
29 {
30         be_ifg_foreach_node(ifg, node) {
31                 neighbours_iter_t neigh_iter;
32
33                 be_ifg_foreach_neighbour(ifg, &neigh_iter, node, neighbour) {
34                         /* interference is bidirectional, but it's enough to dump 1
35                          * direction */
36                         if (get_irn_node_nr(node) >= get_irn_node_nr(neighbour))
37                                 continue;
38
39                         fprintf(F, "edge: {sourcename: ");
40                         print_nodeid(F, node);
41                         fprintf(F, " targetname: ");
42                         print_nodeid(F, neighbour);
43                         fprintf(F, " arrowstyle:none class:1}\n");
44                 }
45         }
46 }
47
48 void be_dump_ifg(FILE *F, ir_graph *irg, const be_ifg_t *ifg)
49 {
50         ir_fprintf(F,
51                 "graph: { title: \"interference graph of %+F\"\n"
52                 "layoutalgorithm: mindepth //$ \"circular\"\n"
53                 "classname 1: \"interference\"\n"
54                 , irg);
55         dump_vcg_infonames(F);
56         dump_vcg_header_colors(F);
57
58         dump_ifg_nodes(F, ifg);
59         dump_ifg_edges(F, ifg);
60
61         fprintf(F, "}\n");
62 }
63
64 static void dump_affinity_edges(FILE *F, const copy_opt_t *co,
65                                 bool dump_costs, bool dump_colors)
66 {
67         co_gs_foreach_aff_node(co, a) {
68                 co_gs_foreach_neighb(a, n) {
69                         /* edges are bidirection, dumping one direction is enough */
70                         if (get_irn_node_nr(a->irn) >= get_irn_node_nr(n->irn))
71                                 continue;
72
73                         fprintf(F, "edge: {sourcename: ");
74                         print_nodeid(F, a->irn);
75                         fprintf(F, " targetname: ");
76                         print_nodeid(F, n->irn);
77                         fprintf(F, " arrowstyle:none");
78
79                         if (dump_costs)
80                                 fprintf(F, " label:\"%d\"", n->costs);
81                         if (dump_colors) {
82                                 const arch_register_t *ar = arch_get_irn_register(a->irn);
83                                 const arch_register_t *nr = arch_get_irn_register(n->irn);
84                                 const char *color = nr == ar ? "blue" : "red";
85                                 fprintf(F, " color:%s", color);
86                         }
87                         fprintf(F, " linestyle:dashed class:2");
88                         fprintf(F, "}\n");
89                 }
90         }
91 }
92
93 void be_dump_ifg_co(FILE *F, const copy_opt_t *co, bool dump_costs,
94                     bool dump_colors)
95 {
96         ir_graph *irg = co->irg;
97         be_ifg_t *ifg = co->cenv->ifg;
98
99         ir_fprintf(F,
100                 "graph: { title: \"interference graph of %+F\"\n"
101                 "layoutalgorithm: mindepth //$ \"circular\"\n"
102                 "classname 1: \"interference\"\n"
103                 "classname 2: \"affinity\"\n"
104                 , irg);
105         dump_vcg_infonames(F);
106         dump_vcg_header_colors(F);
107
108         dump_ifg_nodes(F, ifg);
109         dump_ifg_edges(F, ifg);
110         dump_affinity_edges(F, co, dump_costs, dump_colors);
111
112         fprintf(F, "}\n");
113 }
114
115 static const char *lv_flags_to_str(unsigned flags)
116 {
117         static const char *states[] = {
118                 "---",
119                 "i--",
120                 "-e-",
121                 "ie-",
122                 "--o",
123                 "i-o",
124                 "-eo",
125                 "ieo"
126         };
127
128         return states[flags & 7];
129 }
130
131 void be_dump_liveness_block(be_lv_t *lv, FILE *F, const ir_node *bl)
132 {
133         be_lv_info_t *info = ir_nodehashmap_get(be_lv_info_t, &lv->map, bl);
134
135         fprintf(F, "liveness:\n");
136         if (info != NULL) {
137                 unsigned n = info[0].head.n_members;
138                 unsigned i;
139
140                 for (i = 0; i < n; ++i) {
141                         be_lv_info_node_t *n = &info[i+1].node;
142                         ir_fprintf(F, "%s %+F\n", lv_flags_to_str(n->flags), n->node);
143                 }
144         }
145 }
146
147 typedef struct lv_walker_t {
148         be_lv_t *lv;
149         FILE    *out;
150 } lv_walker_t;
151
152 static void lv_dump_block_walker(ir_node *irn, void *data)
153 {
154         lv_walker_t *w = (lv_walker_t*)data;
155         if (!is_Block(irn))
156                 return;
157         be_dump_liveness_block(w->lv, w->out, irn);
158 }
159
160 void be_liveness_dump(FILE *F, const be_lv_t *lv)
161 {
162         lv_walker_t w;
163
164         w.lv  = (be_lv_t *) lv;
165         w.out = F;
166         irg_block_walk_graph(lv->irg, lv_dump_block_walker, NULL, &w);
167 }