bechordal: Handle Phis more like live-ins instead of regular scheduled nodes in creat...
[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         nodes_iter_t ifg_iter;
24         be_ifg_foreach_node(ifg, &ifg_iter, node) {
25                 dump_node(F, node);
26         }
27 }
28
29 static void dump_ifg_edges(FILE *F, const be_ifg_t *ifg)
30 {
31         nodes_iter_t ifg_iter;
32
33         be_ifg_foreach_node(ifg, &ifg_iter, node) {
34                 neighbours_iter_t neigh_iter;
35
36                 be_ifg_foreach_neighbour(ifg, &neigh_iter, node, neighbour) {
37                         /* interference is bidirectional, but it's enough to dump 1
38                          * direction */
39                         if (get_irn_node_nr(node) >= get_irn_node_nr(neighbour))
40                                 continue;
41
42                         fprintf(F, "edge: {sourcename: ");
43                         print_nodeid(F, node);
44                         fprintf(F, " targetname: ");
45                         print_nodeid(F, neighbour);
46                         fprintf(F, " arrowstyle:none class:1}\n");
47                 }
48         }
49 }
50
51 void be_dump_ifg(FILE *F, ir_graph *irg, const be_ifg_t *ifg)
52 {
53         ir_fprintf(F,
54                 "graph: { title: \"interference graph of %+F\"\n"
55                 "layoutalgorithm: mindepth //$ \"circular\"\n"
56                 "classname 1: \"interference\"\n"
57                 , irg);
58         dump_vcg_infonames(F);
59         dump_vcg_header_colors(F);
60
61         dump_ifg_nodes(F, ifg);
62         dump_ifg_edges(F, ifg);
63
64         fprintf(F, "}\n");
65 }
66
67 static void dump_affinity_edges(FILE *F, const copy_opt_t *co,
68                                 bool dump_costs, bool dump_colors)
69 {
70         co_gs_foreach_aff_node(co, a) {
71                 co_gs_foreach_neighb(a, n) {
72                         /* edges are bidirection, dumping one direction is enough */
73                         if (get_irn_node_nr(a->irn) >= get_irn_node_nr(n->irn))
74                                 continue;
75
76                         fprintf(F, "edge: {sourcename: ");
77                         print_nodeid(F, a->irn);
78                         fprintf(F, " targetname: ");
79                         print_nodeid(F, n->irn);
80                         fprintf(F, " arrowstyle:none");
81
82                         if (dump_costs)
83                                 fprintf(F, " label:\"%d\"", n->costs);
84                         if (dump_colors) {
85                                 const arch_register_t *ar = arch_get_irn_register(a->irn);
86                                 const arch_register_t *nr = arch_get_irn_register(n->irn);
87                                 const char *color = nr == ar ? "blue" : "red";
88                                 fprintf(F, " color:%s", color);
89                         }
90                         fprintf(F, " linestyle:dashed class:2");
91                         fprintf(F, "}\n");
92                 }
93         }
94 }
95
96 void be_dump_ifg_co(FILE *F, const copy_opt_t *co, bool dump_costs,
97                     bool dump_colors)
98 {
99         ir_graph *irg = co->irg;
100         be_ifg_t *ifg = co->cenv->ifg;
101
102         ir_fprintf(F,
103                 "graph: { title: \"interference graph of %+F\"\n"
104                 "layoutalgorithm: mindepth //$ \"circular\"\n"
105                 "classname 1: \"interference\"\n"
106                 "classname 2: \"affinity\"\n"
107                 , irg);
108         dump_vcg_infonames(F);
109         dump_vcg_header_colors(F);
110
111         dump_ifg_nodes(F, ifg);
112         dump_ifg_edges(F, ifg);
113         dump_affinity_edges(F, co, dump_costs, dump_colors);
114
115         fprintf(F, "}\n");
116 }
117
118 static const char *lv_flags_to_str(unsigned flags)
119 {
120         static const char *states[] = {
121                 "---",
122                 "i--",
123                 "-e-",
124                 "ie-",
125                 "--o",
126                 "i-o",
127                 "-eo",
128                 "ieo"
129         };
130
131         return states[flags & 7];
132 }
133
134 void be_dump_liveness_block(be_lv_t *lv, FILE *F, const ir_node *bl)
135 {
136         be_lv_info_t *info = ir_nodehashmap_get(be_lv_info_t, &lv->map, bl);
137
138         fprintf(F, "liveness:\n");
139         if (info != NULL) {
140                 unsigned n = info[0].head.n_members;
141                 unsigned i;
142
143                 for (i = 0; i < n; ++i) {
144                         be_lv_info_node_t *n = &info[i+1].node;
145                         ir_fprintf(F, "%s %+F\n", lv_flags_to_str(n->flags), n->node);
146                 }
147         }
148 }
149
150 typedef struct lv_walker_t {
151         be_lv_t *lv;
152         FILE    *out;
153 } lv_walker_t;
154
155 static void lv_dump_block_walker(ir_node *irn, void *data)
156 {
157         lv_walker_t *w = (lv_walker_t*)data;
158         if (!is_Block(irn))
159                 return;
160         be_dump_liveness_block(w->lv, w->out, irn);
161 }
162
163 void be_liveness_dump(FILE *F, const be_lv_t *lv)
164 {
165         lv_walker_t w;
166
167         w.lv  = (be_lv_t *) lv;
168         w.out = F;
169         irg_block_walk_graph(lv->irg, lv_dump_block_walker, NULL, &w);
170 }