fixed classify_value() function
[libfirm] / ir / stat / stat_dmp.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/ir/stat_dmp.c
4  * Purpose:     Statistics for Firm.
5  * Author:      Michael Beck
6  * Created:
7  * CVS-ID:      $Id$
8  * Copyright:   (c) 2004 Universität Karlsruhe
9  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
10  */
11 #ifdef HAVE_CONFIG_H
12 # include "config.h"
13 #endif
14
15 #include "stat_dmp.h"
16 #include "irhooks.h"
17
18 /**
19  * names of the optimizations
20  */
21 static const char *opt_names[] = {
22   "straightening optimization",
23   "if simplification",
24   "constant evaluation",
25   "algebraic simplification",
26   "Phi optmization",
27   "Write-After-Write optimization",
28   "Write-After-Read optimization",
29   "Read-After-Write optimization",
30   "Read-After-Read optimization",
31   "Read-a-Const optimization",
32   "Tuple optimization",
33   "ID optimization",
34   "Common subexpression elimination",
35   "Strength reduction",
36   "Architecture dependant optimization",
37   "Reassociation optimization",
38   "Polymorphic call optimization",
39   "an if conversion was tried",
40   "Lowered",
41 };
42
43 static const char *if_conv_names[IF_RESULT_LAST] = {
44   "if conv done             ",
45   "if conv side effect      ",
46   "if conv Phi node found   ",
47   "if conv to deep DAG's    ",
48   "if conv bad control flow ",
49   "if conv denied by arch   ",
50 };
51
52 /**
53  * dumps a opcode hash into human readable form
54  */
55 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
56 {
57   node_entry_t *entry;
58   counter_t f_alive;
59   counter_t f_new_node;
60   counter_t f_Id;
61
62   cnt_clr(&f_alive);
63   cnt_clr(&f_new_node);
64   cnt_clr(&f_Id);
65
66   fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
67   for (entry = pset_first(set); entry; entry = pset_next(set)) {
68     fprintf(dmp->f, "%-16s %8u %8u %8u\n",
69       get_id_str(entry->op->name), entry->cnt_alive.cnt[0], entry->new_node.cnt[0], entry->into_Id.cnt[0]);
70
71     cnt_add(&f_alive,    &entry->cnt_alive);
72     cnt_add(&f_new_node, &entry->new_node);
73     cnt_add(&f_Id,       &entry->into_Id);
74   }
75   fprintf(dmp->f, "-------------------------------------------\n");
76   fprintf(dmp->f, "%-16s %8u %8u %8u\n", "Sum",
77      f_alive.cnt[0],
78      f_new_node.cnt[0],
79      f_Id.cnt[0]);
80 }
81
82 /**
83  * dumps an optimization hash into human readable form
84  */
85 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
86 {
87   opt_entry_t *entry = pset_first(set);
88
89   if (entry) {
90     fprintf(dmp->f, "\n%s:\n", opt_names[index]);
91     fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
92
93     for (; entry; entry = pset_next(set)) {
94       fprintf(dmp->f, "%-16s %8u\n",
95         get_id_str(entry->op->name), entry->count.cnt[0]);
96     }
97   }
98 }
99
100 /**
101  * dumps the number of real_function_call optimization
102  */
103 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
104 {
105   if (! cnt_eq(cnt, 0)) {
106     fprintf(dmp->f, "\nReal Function Calls optimized:\n");
107     fprintf(dmp->f, "%-16s %8u\n",
108       "Call", cnt->cnt[0]);
109   }
110 }
111
112 /**
113  * dumps the number of tail_recursion optimization
114  */
115 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
116 {
117   if (num_tail_recursion > 0) {
118     fprintf(dmp->f, "\nTail recursion optimized:\n");
119     fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
120   }
121 }
122
123 /**
124  * dumps the edges count
125  */
126 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
127 {
128   fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt->cnt[0]);
129 }
130
131 /**
132  * dumps the IRG
133  */
134 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
135 {
136   int i, dump_opts = 1;
137   block_entry_t *b_entry;
138
139   if (entry->irg) {
140     ir_graph *const_irg = get_const_code_irg();
141
142     if (entry->irg == const_irg) {
143       fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
144     }
145     else {
146       if (entry->ent)
147         fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
148       else
149         fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
150     }
151
152     fprintf(dmp->f, " %swalked %u over blocks %u:\n"
153                     " was inlined               : %u\n"
154                     " got inlined               : %u\n"
155                     " strength red              : %u\n"
156                     " leaf function             : %s\n"
157                     " calls only leaf functions : %s\n"
158                     " recursive                 : %s\n"
159                     " chain call                : %s\n"
160         " calls                     : %u\n"
161         " indirect calls            : %u\n",
162         entry->is_deleted ? "DELETED " : "",
163         entry->cnt_walked.cnt[0], entry->cnt_walked_blocks.cnt[0],
164         entry->cnt_was_inlined.cnt[0],
165         entry->cnt_got_inlined.cnt[0],
166               entry->cnt_strength_red.cnt[0],
167               entry->is_leaf ? "YES" : "NO",
168               entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
169               entry->is_recursive ? "YES" : "NO",
170               entry->is_chain_call ? "YES" : "NO",
171         entry->cnt_all_calls.cnt[0],
172         entry->cnt_indirect_calls.cnt[0]
173     );
174
175     for (i = 0; i < sizeof(entry->cnt_if_conv)/sizeof(entry->cnt_if_conv[0]); ++i) {
176       fprintf(dmp->f, " %s : %u\n", if_conv_names[i], entry->cnt_if_conv[i].cnt[0]);
177     }
178
179   }
180   else {
181     fprintf(dmp->f, "\nGlobals counts:\n");
182     fprintf(dmp->f, "--------------\n");
183     dump_opts = 0;
184   }
185
186   simple_dump_opcode_hash(dmp, entry->opcode_hash);
187   simple_dump_edges(dmp, &entry->cnt_edges);
188
189   /* effects of optimizations */
190   if (dump_opts) {
191     int i;
192
193     simple_dump_real_func_calls(dmp, &entry->cnt_real_func_call);
194     simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
195
196     for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
197       simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
198     }
199
200     /* dump block info */
201     fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
202     for (b_entry = pset_first(entry->block_hash);
203                b_entry;
204                b_entry = pset_next(entry->block_hash)) {
205       fprintf(dmp->f, "BLK %12ld %12u %12u %12u %12u %12u %4.8f\n",
206               b_entry->block_nr,
207               b_entry->cnt_nodes.cnt[0],
208               b_entry->cnt_edges.cnt[0],
209               b_entry->cnt_in_edges.cnt[0],
210               b_entry->cnt_out_edges.cnt[0],
211               b_entry->cnt_phi_data.cnt[0],
212               (double)b_entry->cnt_edges.cnt[0] / (double)b_entry->cnt_nodes.cnt[0]
213       );
214     }
215   }
216 }
217
218 /**
219  * dumps the IRG
220  */
221 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
222 {
223   int i;
224   counter_t sum;
225
226   cnt_clr(&sum);
227
228   fprintf(dmp->f, "\nConstant Information:\n");
229   fprintf(dmp->f, "---------------------\n");
230
231   fprintf(dmp->f, "\nBit usage for integer constants\n");
232   fprintf(dmp->f, "-------------------------------\n");
233
234   for (i = 0; i < ARR_SIZE(tbl->bits_count); ++i) {
235     fprintf(dmp->f, "%5d %12u\n", i + 1, tbl->bits_count[i].cnt[0]);
236     cnt_add(&sum, &tbl->bits_count[i]);
237   }
238   fprintf(dmp->f, "other %12u\n", tbl->others.cnt[0]);
239   cnt_add(&sum, &tbl->others);
240   fprintf(dmp->f, "-------------------------------\n");
241   fprintf(dmp->f, "sum   %12u\n", sum.cnt[0]);
242 }
243
244 /**
245  * initialize the simple dumper
246  */
247 static void simple_init(dumper_t *dmp, const char *name)
248 {
249   char fname[2048];
250
251   snprintf(fname, sizeof(fname), "%s.txt", name);
252   dmp->f = fopen(fname, "w");
253 }
254
255 /**
256  * finishes the simple dumper
257  */
258 static void simple_finish(dumper_t *dmp)
259 {
260   fclose(dmp->f);
261   dmp->f = NULL;
262 }
263
264 /**
265  * the simple human readable dumper
266  */
267 const dumper_t simple_dumper = {
268   simple_dump_graph,
269   simple_dump_const_tbl,
270   simple_init,
271   simple_finish,
272   NULL,
273   NULL,
274   NULL,
275 };
276
277 /* ---------------------------------------------------------------------- */
278
279 /**
280  * count the nodes as needed:
281  *
282  * 1 normal (data) Phi's
283  * 2 memory Phi's
284  * 3 Proj
285  * 0 all other nodes
286  */
287 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
288 {
289   node_entry_t *entry;
290   int i;
291
292   for (i = 0; i < 4; ++i)
293     cnt_clr(&cnt[i]);
294
295   for (entry = pset_first(graph->opcode_hash); entry; entry = pset_next(graph->opcode_hash)) {
296     if (entry->op == op_Phi) {
297       /* normal Phi */
298       cnt_add(&cnt[1], &entry->cnt_alive);
299     }
300     else if (entry->op == dmp->status->op_PhiM) {
301       /* memory Phi */
302       cnt_add(&cnt[2], &entry->cnt_alive);
303     }
304     else if (entry->op == op_Proj) {
305       /* Proj */
306       cnt_add(&cnt[3], &entry->cnt_alive);
307     }
308     else {
309       /* all other nodes */
310       cnt_add(&cnt[0], &entry->cnt_alive);
311     }
312   }
313 }
314
315 /**
316  * dumps the IRG
317  */
318 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
319 {
320   const char *name;
321
322   counter_t cnt[4];
323
324   if (entry->irg && !entry->is_deleted) {
325     ir_graph *const_irg = get_const_code_irg();
326
327     if (entry->irg == const_irg) {
328       name = "<Const code Irg>";
329       return;
330     }
331     else {
332       if (entry->ent)
333         name = get_entity_name(entry->ent);
334       else
335         name = "<UNKNOWN IRG>";
336     }
337
338     csv_count_nodes(dmp, entry, cnt);
339
340     fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
341         name,
342         (void *)entry->irg,
343         cnt[0].cnt[0],
344         cnt[1].cnt[0],
345         cnt[2].cnt[0],
346         cnt[3].cnt[0]
347     );
348   }
349 }
350
351 /**
352  * dumps the IRG
353  */
354 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
355 {
356   /* FIXME: NYI */
357 }
358
359 /**
360  * initialize the simple dumper
361  */
362 static void csv_init(dumper_t *dmp, const char *name)
363 {
364   char fname[2048];
365
366   snprintf(fname, sizeof(fname), "%s.csv", name);
367   dmp->f = fopen(fname, "a");
368 }
369
370 /**
371  * finishes the simple dumper
372  */
373 static void csv_finish(dumper_t *dmp)
374 {
375   fclose(dmp->f);
376   dmp->f = NULL;
377 }
378
379 /**
380  * the simple human readable dumper
381  */
382 const dumper_t csv_dumper = {
383   csv_dump_graph,
384   csv_dump_const_tbl,
385   csv_init,
386   csv_finish,
387   NULL,
388   NULL,
389   NULL,
390 };