1a1802f5b6001787e79bb7deaf23625c8a868bda
[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 void phi_stat_reset(void) {
63         int i;
64
65         for (i = 0; i < ASIZE; ++i)
66                 curr_vals[i] = 0;
67         curr_vals[I_SPACE1] = -1;
68         curr_vals[I_SPACE2] = -1;
69         curr_vals[I_SPACE3] = -1;
70 }
71
72
73 /**
74  * Collect general data
75  */
76 static void stat_walker(ir_node *node, void *env) {
77         /* count all nodes */
78         curr_vals[I_ALL_NODES]++;
79
80         /* count all block nodes */
81         if (is_Block(node))
82                 curr_vals[I_BLOCKS]++;
83 }
84
85
86 /**
87  * Collect phi node data
88  */
89 static void phi_node_stat(ir_node *node) {
90         int arity, i;
91
92         /* count all phi nodes */
93         curr_vals[I_PHIS]++;
94
95         /* argument count */
96         arity = get_irn_arity(node);
97         curr_vals[I_ARG] += arity;
98         if (arity > MAX_ARITY)
99                 curr_vals[I_ARITY_E]++;
100         else
101                 curr_vals[I_ARITY_S + arity]++;
102
103         /* type of argument {const, pred, glob} */
104         for (i = 0; i < arity; i++) {
105         ir_node *block_of_arg, *block_ith_pred;
106                 ir_node *arg = get_irn_n(node, i);
107
108                 if (iro_Const == get_irn_opcode(arg)) {
109                         curr_vals[I_CONST]++;
110                         continue;
111                 }
112
113                 block_of_arg = get_nodes_block(arg);
114                 block_ith_pred = get_nodes_block(get_irn_n(get_nodes_block(node), i));
115
116                 if (block_of_arg == block_ith_pred) {
117                         curr_vals[I_PRED]++;
118                         continue;
119                 }
120
121                 curr_vals[I_GLOB]++;
122         }
123 }
124
125
126 /**
127  * Collect phi class data
128  */
129 static void phi_class_stat(pset *pc) {
130         int i, o, size, doit, sth_interfered;
131         ir_node **members, *p;
132
133         /* phi class count */
134         curr_vals[I_PHICLS]++;
135
136         /* phi class size */
137         size = pset_count(pc);
138         if (size > MAX_CLS_SIZE)
139                 curr_vals[I_CLS_SIZE_E]++;
140         else
141                 curr_vals[I_CLS_SIZE_S + size]++;
142
143         /* get an array of all members for double iterating */
144         members = malloc(size * sizeof(*members));
145         for (i = 0, p = pset_first(pc); p; p = pset_next(pc))
146                 members[i++] = p;
147         assert(i == size);
148
149         /* determine interference of phi class members */
150         curr_vals[I_VALUES] += size;
151         sth_interfered = 0;
152         for (i = 0; i < size-1; ++i) {
153                 doit = 1;
154                 for (o = i+1; o < size; ++o) {
155                         curr_vals[I_PAIRS]++;
156                         if (phi_ops_interfere(members[i], members[o])) {
157                                 sth_interfered = 1;
158                                 curr_vals[I_PAIRSI]++;
159                                 if (doit) {
160                                         curr_vals[I_VALUESI]++;
161                                         doit = 0;
162                                 }
163                         }
164                 }
165         }
166
167         /* Does this phi class have an inner interference? */
168         curr_vals[I_PHICLSI] += sth_interfered;
169
170         free(members);
171 }
172
173
174 void phi_stat_collect(ir_graph *irg, pset *all_phi_nodes, pset *all_phi_classes) {
175         ir_node *n;
176         pset *pc;
177
178         irg_walk_graph(irg, stat_walker, NULL, NULL);
179         curr_vals[I_BLOCKS] -= 2;
180
181         for (n = pset_first(all_phi_nodes); n; n = pset_next(all_phi_nodes))
182                 phi_node_stat(n);
183
184         for (pc = pset_first(all_phi_classes); pc; pc = pset_next(all_phi_classes))
185                 phi_class_stat(pc);
186 }
187
188
189 /**
190  * Dump statistic values in raw format
191  */
192 static void dump_file(char *filename, int stat[ASIZE]) {
193         FILE *file;
194         int i;
195
196         if (! (file = fopen(filename, "wt"))) {
197                 fprintf(stderr, "Cannot open file for writing: %s\n", filename);
198                 return;
199         }
200
201         for (i = 0; i < ASIZE; i++) {
202                 if (i >= I_ARITY_S && i <= I_ARITY_E)
203                         fprintf(file, "%i %i\n", stat[i], stat[I_PHIS]);
204                 else if (i >= I_CLS_SIZE_S && i <= I_CLS_SIZE_E)
205                         fprintf(file, "%i %i\n", stat[i], stat[I_PHICLS]);
206                 else
207                         fprintf(file, "%i\n", stat[i]);
208         }
209
210     fclose(file);
211 }
212
213
214 void phi_stat_update(char *filename) {
215     int i;
216         FILE *all;
217         int vals[ASIZE];
218
219         if (!filename)
220                 return;
221
222         /* read in */
223         all = fopen(filename, "rt");
224
225     if (all) {
226                 for (i = 0; i < ASIZE; i++) {
227                         if (i >= I_ARITY_S && i <= I_ARITY_E)
228                                 fscanf(all, "%i %i\n", &vals[i], &vals[I_PHIS]);
229                         else if (i >= I_CLS_SIZE_S && i <= I_CLS_SIZE_E)
230                                 fscanf(all, "%i %i\n", &vals[i], &vals[I_PHICLS]);
231                         else
232                                 fscanf(all, "%i\n", &vals[i]);
233                 }
234             fclose(all);
235         } else {
236                 for (i = 0; i < ASIZE; i++)
237                         vals[i] = 0;
238         }
239
240         /* add current values */
241         for (i = 0; i < ASIZE; i++)
242                 vals[i] += curr_vals[i];
243
244         /* write out */
245         dump_file(filename, vals);
246 }
247
248
249 void phi_stat_dump(char *filename) {
250         if (filename)
251                 dump_file(filename, curr_vals);
252 }
253
254
255 void phi_stat_dump_pretty(char *filename) {
256         int i;
257         FILE *out;
258
259         if (! (out = fopen(filename, "wt"))) {
260                 fprintf(stderr, "Cannot open file for writing: %s\n", filename);
261                 return;
262         }
263
264         fprintf(out, "\nPhi argument types\n");
265         fprintf(out, "Total     %4d\n", curr_vals[I_ARG]);
266         fprintf(out, "Constants %4d\n", curr_vals[I_CONST]);
267         fprintf(out, "CF-Pred   %4d\n", curr_vals[I_PRED]);
268         fprintf(out, "Others    %4d\n", curr_vals[I_GLOB]);
269
270         fprintf(out, "\nPhi class interference\n");
271         fprintf(out, "Blocks         %4d\n", curr_vals[I_BLOCKS]);
272         fprintf(out, "Phis           %4d\n", curr_vals[I_PHIS]);
273         fprintf(out, "Interf classes %4d of %4d\n", curr_vals[I_PHICLSI], curr_vals[I_PHICLS]);
274         fprintf(out, "Interf pairs   %4d of %4d\n", curr_vals[I_PAIRSI], curr_vals[I_PAIRS]);
275         fprintf(out, "Interf values  %4d of %4d\n", curr_vals[I_PAIRSI], curr_vals[I_VALUES]);
276
277         fprintf(out, "\nPhi arity\n");
278         for (i = I_ARITY_S; i<=I_ARITY_E; i++)
279                 fprintf(out, "%2i %4d\n", i-I_ARITY_S, curr_vals[i]);
280
281         fprintf(out, "\nPhi class sizes\n");
282         for (i = I_CLS_SIZE_S; i<=I_CLS_SIZE_E; i++)
283                 fprintf(out, "%2i %4d\n", i-I_CLS_SIZE_S, curr_vals[i]);
284
285         fprintf(out, "\n\nTotal nodes:    %4d\n", curr_vals[I_ALL_NODES]);
286
287         fclose(out);
288 }