98bdb47b97acf11f8c69418b680376e5a7f1a96f
[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 #include "bephicongr_t.h"
19 #include "bechordal.h"
20
21
22 #define SUMMARY_FILE_NAME "all.phistat"
23
24 #define MAX_ARITY 10
25 #define MAX_CLS_SIZE 10
26
27 enum vals_t {
28         I_ARG         = 0,
29         I_CONST,
30         I_PRED,
31         I_GLOB,
32
33         I_SPACE1,
34         I_BLOCKS,
35         I_PHIS,
36         I_PHICLS,
37         I_PHICLSI,
38         I_PAIRS,
39         I_PAIRSI,
40         I_VALUES,
41         I_VALUESI,
42
43         I_SPACE2,
44         I_ARITY_S,
45         I_ARITY_E    = I_ARITY_S+MAX_ARITY,
46
47         I_SPACE3,
48         I_CLS_SIZE_S,
49         I_CLS_SIZE_E = I_CLS_SIZE_S+MAX_CLS_SIZE,
50         I_ALL_NODES,
51         ASIZE
52 };
53
54 static int curr_vals[ASIZE];
55
56
57 /**
58  * Dump statistic values and some annotations for current irp
59  */
60 static void dump_file(void) {
61         int i, next;
62         FILE *out;
63         char buf[200];
64
65         next = sprintf(buf, get_irp_prog_name());
66         sprintf(buf+next, ".phistat");
67         out = fopen(buf, "wt");
68
69         fprintf(out, "\nPhi argument types\n");
70         fprintf(out, "Total     %4d\n", curr_vals[I_ARG]);
71         fprintf(out, "Constants %4d\n", curr_vals[I_CONST]);
72         fprintf(out, "CF-Pred   %4d\n", curr_vals[I_PRED]);
73         fprintf(out, "Others    %4d\n", curr_vals[I_GLOB]);
74
75         fprintf(out, "\nPhi class interference\n");
76         fprintf(out, "Blocks         %4d\n", curr_vals[I_BLOCKS]);
77         fprintf(out, "Phis           %4d\n", curr_vals[I_PHIS]);
78         fprintf(out, "Interf classes %4d of %4d\n", curr_vals[I_PHICLSI], curr_vals[I_PHICLS]);
79         fprintf(out, "Interf pairs   %4d of %4d\n", curr_vals[I_PAIRSI], curr_vals[I_PAIRS]);
80         fprintf(out, "Interf values  %4d of %4d\n", curr_vals[I_PAIRSI], curr_vals[I_VALUES]);
81
82         fprintf(out, "\nPhi arity\n");
83         for (i = I_ARITY_S; i<=I_ARITY_E; i++)
84                 fprintf(out, "%2i %4d\n", i-I_ARITY_S, curr_vals[i]);
85
86         fprintf(out, "\nPhi class sizes\n");
87         for (i = I_CLS_SIZE_S; i<=I_CLS_SIZE_E; i++)
88                 fprintf(out, "%2i %4d\n", i-I_CLS_SIZE_S, curr_vals[i]);
89
90         fprintf(out, "\n\nTotal nodes:    %4d\n", curr_vals[I_ALL_NODES]);
91
92         fclose(out);
93 }
94
95
96 /**
97  * Updates the summary file with cumulated values
98  */
99 static void update_all_file(void) {
100     int i;
101         FILE *all;
102         int vals[ASIZE];
103
104         /* read in */
105         all = fopen(SUMMARY_FILE_NAME, "rt");
106     if (all) {
107                 for (i = 0; i<ASIZE; i++) {
108                         if (i >= I_ARITY_S && i <= I_ARITY_E)
109                                 fscanf(all, "%i %i\n", &vals[i], &vals[I_ALL_NODES]);
110                         else
111                                 fscanf(all, "%i\n", &vals[i]);
112                 }
113             fclose(all);
114         } else {
115                 for (i = 0; i<ASIZE; i++)
116                         vals[i] = 0;
117         }
118
119         /* write out */
120         all = fopen(SUMMARY_FILE_NAME, "wt");
121         for (i = 0; i<ASIZE; i++) {
122                 if (i >= I_ARITY_S && i <= I_ARITY_E)
123                         fprintf(all, "%i %i\n", vals[i]+curr_vals[i], vals[I_ALL_NODES]+curr_vals[I_ALL_NODES]);
124                 else
125                         fprintf(all, "%i\n", vals[i]+curr_vals[i]);
126         }
127     fclose(all);
128 }
129
130 /**
131  * Collect the statistical data
132  */
133 static void phi_stat_walker(ir_node *node, void *env) {
134         int arity, i;
135
136         /* count all nodes */
137         curr_vals[I_ALL_NODES]++;
138
139         /* count all block nodes */
140         if (is_Block(node))
141                 curr_vals[I_BLOCKS]++;
142
143         if (!(is_Phi(node) && mode_is_datab(get_irn_mode(node)))) return;
144
145         /* count all phi nodes */
146         curr_vals[I_PHIS]++;
147
148         /* argument count */
149         arity = get_irn_arity(node);
150         curr_vals[I_ARG] += arity;
151         if (arity > MAX_ARITY)
152                 curr_vals[I_ARITY_E]++;
153         else
154                 curr_vals[I_ARITY_S + arity]++;
155
156         /* type of argument */
157         for (i = 0; i < arity; i++) {
158         ir_node *block_of_arg, *block_ith_pred;
159                 ir_node *arg = get_irn_n(node, i);
160
161                 if (iro_Const == get_irn_opcode(arg)) {
162                         curr_vals[I_CONST]++;
163                         continue;
164                 }
165
166                 block_of_arg = get_nodes_block(arg);
167                 block_ith_pred = get_nodes_block(get_irn_n(get_nodes_block(node), i));
168
169                 if (block_of_arg == block_ith_pred) {
170                         curr_vals[I_PRED]++;
171                         continue;
172                 }
173
174                 curr_vals[I_GLOB]++;
175         }
176
177 }
178
179 static void phi_class_stat_walker(ir_node *node, void *env) {
180         int i, o, size, doit, sth_interfered;
181         ir_node **members, *p;
182         pset *pc;
183
184         pc = get_phi_class(node);
185         if (pc) {
186
187                 /* phi class count */
188                 curr_vals[I_PHICLS]++;
189
190                 /* phi class size */
191                 size = pset_count(pc);
192                 if (size > MAX_CLS_SIZE)
193                         curr_vals[I_CLS_SIZE_E]++;
194                 else
195                         curr_vals[I_CLS_SIZE_S + size]++;
196
197                 /* count interfering pairs / values */
198                 members = (ir_node **) malloc(size * sizeof(ir_node*));
199
200                 for (i=0, p = (ir_node *)pset_first(pc); p; p = (ir_node *)pset_next(pc))
201                         members[i++] = p;
202                 assert(i == size);
203
204                 /* determine interference of phi args */
205                 curr_vals[I_VALUES] += size;
206                 sth_interfered = 0;
207                 for (i = 0; i < size-1; ++i) {
208                         doit = 1;
209                         for (o = i+1; o < size; ++o) {
210                                 curr_vals[I_PAIRS]++;
211                                 if (phi_ops_interfere(members[i], members[o])) {
212                                         sth_interfered = 1;
213                                         curr_vals[I_PAIRSI]++;
214                                         if (doit) {
215                                                 curr_vals[I_VALUESI]++;
216                                                 doit = 0;
217                                         }
218                                 }
219                         }
220                 }
221
222                 /* has this phi class an interference? */
223                 curr_vals[I_PHICLSI] += sth_interfered;
224                 free(members);
225         }
226 }
227
228
229 void do_phi_statistics(void) {
230         int i, n;
231         curr_vals[I_SPACE1] = -1;
232         curr_vals[I_SPACE2] = -1;
233         curr_vals[I_SPACE3] = -1;
234
235         for (i = 0, n = get_irp_n_irgs(); i < n; i++) {
236                 ir_graph *irg = get_irp_irg(i);
237                 irg_walk_graph(irg, phi_stat_walker, NULL, NULL);
238                 irg_walk_graph(irg, phi_class_stat_walker, NULL, NULL);
239                 curr_vals[I_BLOCKS] -= 2;
240         }
241
242         dump_file();
243         update_all_file();
244 }