Added more phi statistics. Fixed bug in phi congruence classes.
[libfirm] / ir / be / phistat.c
1 #include <stdio.h>
2 #include <string.h>
3
4 #include "config.h"
5
6 #include "irgraph.h"
7 #include "irnode.h"
8 #include "irgwalk.h"
9 #include "irop.h"
10 #include "irprog.h"
11 #include "irmode_t.h"
12 #include "bephicongr_t.h"
13
14
15 #define SUMMARY_FILE_NAME "all.phi"
16
17 #define ARG_CNT_MAX 10
18 #define PHI_CLS_MAX 10
19
20 #define I_PHI_CNT   0
21 #define I_BLK_CNT   (I_PHI_CNT+1)
22 #define I_SPACE3    (I_BLK_CNT+1)
23 #define I_ARG_CNT_S (I_SPACE3+1)
24 #define I_ARG_CNT_E (I_ARG_CNT_S+ARG_CNT_MAX)
25 #define I_SPACE1    (I_ARG_CNT_E+1)
26 #define I_PHI_CLS_S (I_SPACE1+1)
27 #define I_PHI_CLS_E (I_PHI_CLS_S+PHI_CLS_MAX)
28 #define I_SPACE2    (I_PHI_CLS_E+1)
29 #define I_INTERFP       (I_SPACE2+1)         /* number of interfering pairs */
30 #define I_INTERFV       (I_INTERFP+1)        /* number of interfering values */
31 #define I_PHICLSCNT (I_INTERFV+1)        /* number of phi classes */
32 #define I_INTERFPHI     (I_PHICLSCNT+1)      /* number of phi classes which have interfering vals */
33 #define I_CONST     (I_INTERFPHI+1)
34 #define I_PRED      (I_CONST+1)
35 #define I_GLOB      (I_PRED+1)
36
37 #define ASIZE (I_GLOB+1)
38 static int curr_vals[ASIZE];
39
40
41 static void phi_stat_walker(ir_node *node, void *env) {
42         int count, i, size;
43
44         /* count all block nodes */
45         if (is_Block(node))
46                 curr_vals[I_BLK_CNT]++;
47
48         if (!(is_Phi(node) && mode_is_datab(get_irn_mode(node)))) return;
49
50         /* count all phi nodes */
51         curr_vals[I_PHI_CNT]++;
52
53         /* argument count */
54         count = get_irn_arity(node);
55         if (count > ARG_CNT_MAX)
56                 curr_vals[I_ARG_CNT_E]++;
57         else
58                 curr_vals[I_ARG_CNT_S + count]++;
59
60         /* type of argument */
61         for (i = 0; i < count; i++) {
62                 ir_node *arg = get_irn_n(node, i);
63
64                 if (iro_Const == get_irn_opcode(arg)) {
65                         curr_vals[I_CONST]++;
66                         continue;
67                 }
68
69                 ir_node *block_of_arg = get_nodes_block(arg);
70                 ir_node *block_ith_pred = get_nodes_block(get_irn_n(get_nodes_block(node), i));
71
72                 if (block_of_arg == block_ith_pred) {
73                         curr_vals[I_PRED]++;
74                         continue;
75                 }
76
77                 curr_vals[I_GLOB]++;
78         }
79
80
81         size = get_phi_class_size(node);
82         /* phi class count */
83         if (size > 0)
84                 curr_vals[I_PHICLSCNT]++;
85
86         /* phi class size */
87         if (size > PHI_CLS_MAX)
88                 curr_vals[I_PHI_CLS_E]++;
89         else
90                 curr_vals[I_PHI_CLS_S + size]++;
91
92         /* count of interfering pairs / values */
93         curr_vals[I_INTERFP] += get_irn_phi_info(node)->interf_pairs;
94         curr_vals[I_INTERFV] += get_irn_phi_info(node)->interf_vals;
95         if (get_irn_phi_info(node)->interf_vals > 0)
96                 curr_vals[I_INTERFPHI]++;
97 }
98
99
100 /**
101  * Dump values and some annotations for current irp
102  */
103 static void dump_files(void) {
104         int i, sum1, sum2, sum3, next;
105         FILE *out;
106         char buf[200];
107
108         sum1 = curr_vals[I_CONST] + curr_vals[I_PRED] + curr_vals[I_GLOB];
109         sum2 = 0;
110         for (i = I_ARG_CNT_S; i<=I_ARG_CNT_E; i++)
111                 sum2 += curr_vals[i];
112         sum3 = 0;
113         for (i = I_PHI_CLS_S; i<=I_PHI_CLS_E; i++)
114                 sum3 += curr_vals[i];
115
116         next = sprintf(buf, get_irp_prog_name());
117         sprintf(buf+next, ".phi.stat");
118         out = fopen(buf, "wt");
119
120         fprintf(out, "Phis %i\n", curr_vals[I_PHI_CNT]);
121         fprintf(out, "Blks %i\n", curr_vals[I_BLK_CNT]);
122
123         fprintf(out, "\nArgument counts\n");
124         for (i = I_ARG_CNT_S; i<=I_ARG_CNT_E; i++)
125                 fprintf(out, "%2i %2.4f\n", i-I_ARG_CNT_S, (double) curr_vals[i] / sum2);
126
127         fprintf(out, "\nPhi class sizes\n");
128         for (i = I_PHI_CLS_S; i<=I_PHI_CLS_E; i++)
129                 fprintf(out, "%2i %2.4f\n", i-I_PHI_CLS_S, (double) curr_vals[i] / sum3);
130
131         fprintf(out, "\n");
132         fprintf(out, "Interf Pairs %d\n", curr_vals[I_INTERFP]);
133         fprintf(out, "Interf Values %d\n", curr_vals[I_INTERFV]);
134         fprintf(out, "PhiCls Count %d\n", curr_vals[I_PHICLSCNT]);
135         fprintf(out, "Interf PhisCl %d\n", curr_vals[I_INTERFPHI]);
136         fprintf(out, "Const %2.2f\n", (double) curr_vals[I_CONST] / sum1);
137         fprintf(out, "Pred %2.2f\n", (double) curr_vals[I_PRED] / sum1);
138         fprintf(out, "Glob %2.2f\n", (double) curr_vals[I_GLOB] / sum1);
139
140         fclose(out);
141 }
142
143
144 /**
145  * Updates the summary file with cumulated values
146  */
147 static void update_all_file(void) {
148     int i;
149         FILE *all;
150         int vals[ASIZE];
151
152         /* read in */
153         all = fopen(SUMMARY_FILE_NAME, "rt");
154     if (all) {
155                 for (i = 0; i<ASIZE; i++)
156                         fscanf(all, "%i\n", &vals[i]);
157             fclose(all);
158         } else {
159                 for (i = 0; i<ASIZE; i++)
160                         vals[i] = 0;
161         }
162
163         /* write out */
164         all = fopen(SUMMARY_FILE_NAME, "wt");
165         for (i = 0; i<ASIZE; i++)
166                 fprintf(all, "%i\n", vals[i]+curr_vals[i]);
167     fclose(all);
168 }
169
170 void do_phi_statistics(void) {
171         int i, n;
172         curr_vals[I_SPACE1] = -1;
173         curr_vals[I_SPACE2] = -1;
174         curr_vals[I_SPACE3] = -1;
175
176         for (i = 0, n = get_irp_n_irgs(); i < n; i++) {
177                 ir_graph *irg = get_irp_irg(i);
178                 irg_walk_graph(irg, phi_stat_walker, NULL, NULL);
179                 curr_vals[I_BLK_CNT] -= 2;
180         }
181
182         dump_files();
183         update_all_file();
184 }