Added phi stat dump option
[libfirm] / ir / be / phistat.c
1 /**
2  * @author Daniel Grund
3  * @date 09.12.2004
4  */
5
6 #include <stdio.h>
7 #include <string.h>
8 #include <stdlib.h>
9
10 #include "config.h"
11
12 #include "irgraph.h"
13 #include "irnode.h"
14 #include "irgwalk.h"
15 #include "irop.h"
16 #include "irprog.h"
17 #include "irmode_t.h"
18
19 #include "bechordal.h"
20 #include "phistat.h"
21
22 #define MAX_ARITY 10
23 #define MAX_CLS_SIZE 10
24
25 /**
26  * For an explanation of these values see phi_stat_dump_pretty
27  */
28 enum vals_t {
29         I_ARG         = 0,
30         I_CONST,
31         I_PRED,
32         I_GLOB,
33
34         I_SPACE1,
35         I_BLOCKS,
36         I_PHIS,
37         I_PHICLS,
38         I_PHICLSI,
39         I_PAIRS,
40         I_PAIRSI,
41         I_VALUES,
42         I_VALUESI,
43
44         I_SPACE2,
45         I_ARITY_S,
46         I_ARITY_E    = I_ARITY_S+MAX_ARITY,
47
48         I_SPACE3,
49         I_CLS_SIZE_S,
50         I_CLS_SIZE_E = I_CLS_SIZE_S+MAX_CLS_SIZE,
51         I_ALL_NODES,
52         ASIZE
53 };
54
55 /**
56  * Holds current values. Values are added till next
57  * phi_stat_reset
58  */
59 static int curr_vals[ASIZE];
60
61
62 /**
63  * Resets the array holding the data
64  */
65 void phi_stat_reset(void) {
66         int i;
67
68         for (i = 0; i < ASIZE; ++i)
69                 curr_vals[i] = 0;
70         curr_vals[I_SPACE1] = -1;
71         curr_vals[I_SPACE2] = -1;
72         curr_vals[I_SPACE3] = -1;
73 }
74
75
76 /**
77  * Collect general data
78  */
79 static void stat_walker(ir_node *node, void *env) {
80         /* count all nodes */
81         curr_vals[I_ALL_NODES]++;
82
83         /* count all block nodes */
84         if (is_Block(node))
85                 curr_vals[I_BLOCKS]++;
86 }
87
88
89 /**
90  * Collect phi node data
91  */
92 static void phi_node_stat(ir_node *node) {
93         int arity, i;
94
95         /* count all phi nodes */
96         curr_vals[I_PHIS]++;
97
98         /* argument count */
99         arity = get_irn_arity(node);
100         curr_vals[I_ARG] += arity;
101         if (arity > MAX_ARITY)
102                 curr_vals[I_ARITY_E]++;
103         else
104                 curr_vals[I_ARITY_S + arity]++;
105
106         /* type of argument {const, pred, glob} */
107         for (i = 0; i < arity; i++) {
108         ir_node *block_of_arg, *block_ith_pred;
109                 ir_node *arg = get_irn_n(node, i);
110
111                 if (iro_Const == get_irn_opcode(arg)) {
112                         curr_vals[I_CONST]++;
113                         continue;
114                 }
115
116                 block_of_arg = get_nodes_block(arg);
117                 block_ith_pred = get_nodes_block(get_irn_n(get_nodes_block(node), i));
118
119                 if (block_of_arg == block_ith_pred) {
120                         curr_vals[I_PRED]++;
121                         continue;
122                 }
123
124                 curr_vals[I_GLOB]++;
125         }
126 }
127
128
129 /**
130  * Collect phi class data
131  */
132 static void phi_class_stat(pset *pc) {
133         int i, o, size, doit, sth_interfered;
134         ir_node **members, *p;
135
136         /* phi class count */
137         curr_vals[I_PHICLS]++;
138
139         /* phi class size */
140         size = pset_count(pc);
141         if (size > MAX_CLS_SIZE)
142                 curr_vals[I_CLS_SIZE_E]++;
143         else
144                 curr_vals[I_CLS_SIZE_S + size]++;
145
146         /* get an array of all members for double iterating */
147         members = (ir_node **) malloc(size * sizeof(ir_node*));
148         for (i=0, p = (ir_node *)pset_first(pc); p; p = (ir_node *)pset_next(pc))
149                 members[i++] = p;
150         assert(i == size);
151
152         /* determine interference of phi class members */
153         curr_vals[I_VALUES] += size;
154         sth_interfered = 0;
155         for (i = 0; i < size-1; ++i) {
156                 doit = 1;
157                 for (o = i+1; o < size; ++o) {
158                         curr_vals[I_PAIRS]++;
159                         if (phi_ops_interfere(members[i], members[o])) {
160                                 sth_interfered = 1;
161                                 curr_vals[I_PAIRSI]++;
162                                 if (doit) {
163                                         curr_vals[I_VALUESI]++;
164                                         doit = 0;
165                                 }
166                         }
167                 }
168         }
169
170         /* Does this phi class have an inner interference? */
171         curr_vals[I_PHICLSI] += sth_interfered;
172
173         free(members);
174 }
175
176
177 /**
178  * Collect all stat data
179  */
180 void phi_stat_collect(ir_graph *irg, pset *all_phi_nodes, pset *all_phi_classes) {
181         ir_node *n;
182         pset *pc;
183
184         irg_walk_graph(irg, stat_walker, NULL, NULL);
185         curr_vals[I_BLOCKS] -= 2;
186
187         for (n = (ir_node *)pset_first(all_phi_nodes); n; n = (ir_node *)pset_next(all_phi_nodes))
188                 phi_node_stat(n);
189
190         for (pc = (pset *)pset_first(all_phi_classes); pc; pc = (pset *)pset_next(all_phi_classes))
191                 phi_class_stat(pc);
192 }
193
194
195 /**
196  * Dump statistic values in raw format
197  */
198 static void dump_file(char *filename, int stat[ASIZE]) {
199         FILE *file;
200         int i;
201
202         if (! (file = fopen(filename, "wt"))) {
203                 fprintf(stderr, "Cannot open file for writing: %s\n", filename);
204                 return;
205         }
206
207         for (i = 0; i < ASIZE; i++) {
208                 if (i >= I_ARITY_S && i <= I_ARITY_E)
209                         fprintf(file, "%i %i\n", stat[i], stat[I_PHIS]);
210                 else if (i >= I_CLS_SIZE_S && i <= I_CLS_SIZE_E)
211                         fprintf(file, "%i %i\n", stat[i], stat[I_PHICLS]);
212                 else
213                         fprintf(file, "%i\n", stat[i]);
214         }
215
216     fclose(file);
217 }
218
219
220 /**
221  * Updates a cumulative file with the current values.
222  */
223 void phi_stat_update(char *filename) {
224     int i;
225         FILE *all;
226         int vals[ASIZE];
227
228         if (!filename)
229                 return;
230
231         /* read in */
232         all = fopen(filename, "rt");
233
234     if (all) {
235                 for (i = 0; i < ASIZE; i++) {
236                         if (i >= I_ARITY_S && i <= I_ARITY_E)
237                                 fscanf(all, "%i %i\n", &vals[i], &vals[I_PHIS]);
238                         else if (i >= I_CLS_SIZE_S && i <= I_CLS_SIZE_E)
239                                 fscanf(all, "%i %i\n", &vals[i], &vals[I_PHICLS]);
240                         else
241                                 fscanf(all, "%i\n", &vals[i]);
242                 }
243             fclose(all);
244         } else {
245                 for (i = 0; i < ASIZE; i++)
246                         vals[i] = 0;
247         }
248
249         /* add current values */
250         for (i = 0; i < ASIZE; i++)
251                 vals[i] += curr_vals[i];
252
253         /* write out */
254         dump_file(filename, vals);
255 }
256
257
258 /**
259  * Dumps the current contents of the values array to a file.
260  * Updates a cumulative file.
261  */
262 void phi_stat_dump(char *filename) {
263         if (filename)
264                 dump_file(filename, curr_vals);
265 }
266
267
268 /**
269  * Dumps the current contents of the values array
270  * and annotations to a file.
271  */
272 void phi_stat_dump_pretty(char *filename) {
273         int i;
274         FILE *out;
275
276         if (! (out = fopen(filename, "wt"))) {
277                 fprintf(stderr, "Cannot open file for writing: %s\n", filename);
278                 return;
279         }
280
281         fprintf(out, "\nPhi argument types\n");
282         fprintf(out, "Total     %4d\n", curr_vals[I_ARG]);
283         fprintf(out, "Constants %4d\n", curr_vals[I_CONST]);
284         fprintf(out, "CF-Pred   %4d\n", curr_vals[I_PRED]);
285         fprintf(out, "Others    %4d\n", curr_vals[I_GLOB]);
286
287         fprintf(out, "\nPhi class interference\n");
288         fprintf(out, "Blocks         %4d\n", curr_vals[I_BLOCKS]);
289         fprintf(out, "Phis           %4d\n", curr_vals[I_PHIS]);
290         fprintf(out, "Interf classes %4d of %4d\n", curr_vals[I_PHICLSI], curr_vals[I_PHICLS]);
291         fprintf(out, "Interf pairs   %4d of %4d\n", curr_vals[I_PAIRSI], curr_vals[I_PAIRS]);
292         fprintf(out, "Interf values  %4d of %4d\n", curr_vals[I_PAIRSI], curr_vals[I_VALUES]);
293
294         fprintf(out, "\nPhi arity\n");
295         for (i = I_ARITY_S; i<=I_ARITY_E; i++)
296                 fprintf(out, "%2i %4d\n", i-I_ARITY_S, curr_vals[i]);
297
298         fprintf(out, "\nPhi class sizes\n");
299         for (i = I_CLS_SIZE_S; i<=I_CLS_SIZE_E; i++)
300                 fprintf(out, "%2i %4d\n", i-I_CLS_SIZE_S, curr_vals[i]);
301
302         fprintf(out, "\n\nTotal nodes:    %4d\n", curr_vals[I_ALL_NODES]);
303
304         fclose(out);
305 }