if conversiopn currently cannot cope with Bad control flow predecessor
[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 struct {
22         hook_opt_kind kind;
23         const char    *name;
24 } opt_names[] = {
25         { HOOK_OPT_DEAD_BLOCK,   "dead block elimination" },
26         { HOOK_OPT_STG,          "straightening optimization" },
27         { HOOK_OPT_IFSIM,        "if simplification" },
28         { HOOK_OPT_CONST_EVAL,   "constant evaluation" },
29         { HOOK_OPT_ALGSIM,       "algebraic simplification" },
30         { HOOK_OPT_PHI,          "Phi optmization" },
31         { HOOK_OPT_SYNC,         "Sync optmization" },
32         { HOOK_OPT_WAW,          "Write-After-Write optimization" },
33         { HOOK_OPT_WAR,          "Write-After-Read optimization" },
34         { HOOK_OPT_RAW,          "Read-After-Write optimization" },
35         { HOOK_OPT_RAR,          "Read-After-Read optimization" },
36         { HOOK_OPT_RC,           "Read-a-Const optimization" },
37         { HOOK_OPT_TUPLE,        "Tuple optimization" },
38         { HOOK_OPT_ID,           "ID optimization" },
39         { HOOK_OPT_CSE,          "Common subexpression elimination" },
40         { HOOK_OPT_STRENGTH_RED, "Strength reduction" },
41         { HOOK_OPT_ARCH_DEP,     "Architecture dependant optimization" },
42         { HOOK_OPT_REASSOC,      "Reassociation optimization" },
43         { HOOK_OPT_POLY_CALL,    "Polymorphic call optimization" },
44         { HOOK_OPT_IF_CONV,      "an if conversion was tried" },
45         { HOOK_OPT_FUNC_CALL,    "Real function call optimization" },
46         { HOOK_OPT_CONFIRM,      "Confirm-based optimization: replacement" },
47         { HOOK_OPT_CONFIRM_C,    "Confirm-based optimization: replaced by const" },
48         { HOOK_OPT_CONFIRM_E,    "Confirm-based optimization: evaluated" },
49         { HOOK_OPT_EXC_REM,      "a exception edge was removed due to a Confirmation prove" },
50         { HOOK_LOWERED,          "Lowered" },
51         { HOOK_BACKEND,          "Backend transformation" },
52         { FS_OPT_NEUTRAL_0,      "algebraic simplification: a op 0 = 0 op a = a" },
53         { FS_OPT_NEUTRAL_1,      "algebraic simplification: a op 1 = 1 op a = a" },
54         { FS_OPT_ADD_A_A,        "algebraic simplification: a + a = a * 2" },
55         { FS_OPT_ADD_A_MINUS_B,  "algebraic simplification: a + -b = a - b" },
56         { FS_OPT_ADD_SUB,        "algebraic simplification: (a + x) - x = (a - x) + x = a" },
57         { FS_OPT_ADD_MUL_A_X_A,  "algebraic simplification: a * x + a = a * (x + 1)" },
58         { FS_OPT_SUB_0_A,        "algebraic simplification: 0 - a = -a" },
59         { FS_OPT_SUB_MUL_A_X_A,  "algebraic simplification: a * x - a = a * (x - 1)" },
60         { FS_OPT_SUB_SUB_X_Y_Z,  "algebraic simplification: (x - y) - z = x - (y + z)" },
61         { FS_OPT_MUL_MINUS_1,    "algebraic simplification: a * -1 = -a" },
62         { FS_OPT_OR,             "algebraic simplification: a | a = a | 0 = 0 | a = a" },
63         { FS_OPT_AND,            "algebraic simplification: a & 0b1...1 = 0b1...1 & a =  a & a = a" },
64         { FS_OPT_EOR_A_A,        "algebraic simplification: a ^ a = 0" },
65         { FS_OPT_EOR_TO_NOT_BOOL,"algebraic simplification: bool ^ 1 = !bool" },
66         { FS_OPT_EOR_TO_NOT,     "algebraic simplification: x ^ 0b1..1 = ~x" },
67         { FS_OPT_NOT_CMP,        "algebraic simplification: !(a cmp b) = a !cmp b" },
68         { FS_OPT_OR_SHFT_TO_ROT, "algebraic simplification: (x << c) | (x >> (bits - c)) == Rot(x, c)" },
69         { FS_OPT_REASSOC_SHIFT,  "algebraic simplification: (x SHF c1) SHF c2 = x SHF (c1+c2)" },
70         { FS_OPT_CONV,           "algebraic simplification: Conv could be removed" },
71         { FS_OPT_CAST,           "algebraic simplification: a Cast could be removed" },
72         { FS_OPT_MIN_MAX_EQ,     "algebraic simplification: Min(a,a) = Max(a,a) = a" },
73         { FS_OPT_MUX_C,          "algebraic simplification: Mux(C, f, t) = C ? t : f" },
74         { FS_OPT_MUX_EQ,         "algebraic simplification: Mux(v, x, x) = x" },
75         { FS_OPT_MUX_TRANSFORM,  "algebraic simplification: Mux(a, b, c) = b OR Mux(a,b, c) = c" },
76         { FS_OPT_MUX_TO_MIN,     "algebraic simplification: Mux(a < b, a, b) = Min(a,b)" },
77         { FS_OPT_MUX_TO_MAX,     "algebraic simplification: Mux(a > b, a, b) = Max(a,b)" },
78         { FS_OPT_MUX_TO_ABS,     "algebraic simplification: Mux(a > b, a, b) = Abs(a,b)" },
79         { FS_OPT_MUX_TO_SHR,     "algebraic simplification: Mux(a > b, a, b) = a >> b" },
80         { FS_BE_IA32_LEA,        "ia32 Backend transformation: Lea was created" },
81         { FS_BE_IA32_LOAD_LEA,   "ia32 Backend transformation: Load merged with a Lea" },
82         { FS_BE_IA32_STORE_LEA,  "ia32 Backend transformation: Store merged with a Lea" },
83         { FS_BE_IA32_AM_S,       "ia32 Backend transformation: Source address mode node created" },
84         { FS_BE_IA32_AM_D,       "ia32 Backend transformation: Destination address mode node created" },
85         { FS_BE_IA32_CJMP,       "ia32 Backend transformation: CJmp created to save a cmp/test" },
86         { FS_BE_IA32_2ADDRCPY,   "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
87         { FS_BE_IA32_SPILL2ST,   "ia32 Backend transformation: Created Store for a Spill" },
88         { FS_BE_IA32_RELOAD2LD,  "ia32 Backend transformation: Created Load for a Reload" },
89         { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
90         { FS_BE_IA32_LEA2ADD,    "ia32 Backend transformation: Transformed Lea back into Add" },
91 };
92
93 static const char *if_conv_names[IF_RESULT_LAST] = {
94         "if conv done             ",
95         "if conv side effect      ",
96         "if conv Phi node found   ",
97         "if conv to deep DAG's    ",
98         "if conv bad control flow ",
99         "if conv denied by arch   ",
100 };
101
102 /**
103  * dumps a opcode hash into human readable form
104  */
105 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
106 {
107         node_entry_t *entry;
108         counter_t f_alive;
109         counter_t f_new_node;
110         counter_t f_Id;
111
112         cnt_clr(&f_alive);
113         cnt_clr(&f_new_node);
114         cnt_clr(&f_Id);
115
116         fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
117         foreach_pset(set, entry) {
118                 fprintf(dmp->f, "%-16s %8u %8u %8u\n",
119                         get_id_str(entry->op->name),
120                         cnt_to_uint(&entry->cnt_alive),
121                         cnt_to_uint(&entry->new_node),
122                         cnt_to_uint(&entry->into_Id)
123                 );
124
125                 cnt_add(&f_alive,    &entry->cnt_alive);
126                 cnt_add(&f_new_node, &entry->new_node);
127                 cnt_add(&f_Id,       &entry->into_Id);
128         }
129         fprintf(dmp->f, "-------------------------------------------\n");
130         fprintf(dmp->f, "%-16s %8u %8u %8u\n", "Sum",
131                 cnt_to_uint(&f_alive),
132                 cnt_to_uint(&f_new_node),
133                 cnt_to_uint(&f_Id)
134         );
135 }
136
137 /**
138  * dumps an optimization hash into human readable form
139  */
140 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
141 {
142         assert(index < ARR_SIZE(opt_names) && "index out of range");
143         assert(opt_names[index].kind == index && "opt_names broken");
144
145         if (pset_count(set) > 0) {
146                 opt_entry_t *entry;
147
148                 fprintf(dmp->f, "\n%s:\n", opt_names[index].name);
149                 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
150
151                 foreach_pset(set, entry) {
152                         fprintf(dmp->f, "%-16s %8u\n",
153                                 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
154                 }
155         }
156 }
157
158 /**
159  * dumps the register pressure for each block and for each register class
160  */
161 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
162 {
163         be_block_entry_t     *b_entry = pset_first(entry->be_block_hash);
164         reg_pressure_entry_t *rp_entry;
165
166         /* return if no be statistic information available */
167         if (! b_entry)
168                 return;
169
170         fprintf(dmp->f, "\nREG PRESSURE:\n");
171         fprintf(dmp->f, "%12s", "Block Nr");
172
173         /* print table head (register class names) */
174         foreach_pset(b_entry->reg_pressure, rp_entry)
175                 fprintf(dmp->f, "%15s", rp_entry->class_name);
176         fprintf(dmp->f, "\n");
177
178         /* print the reg pressure for all blocks and register classes */
179         for (/* b_entry is already initialized */ ;
180              b_entry;
181              b_entry = pset_next(entry->be_block_hash)) {
182                 fprintf(dmp->f, "BLK   %6ld", b_entry->block_nr);
183
184                 foreach_pset(b_entry->reg_pressure, rp_entry)
185                         fprintf(dmp->f, "%15d", rp_entry->pressure);
186                 fprintf(dmp->f, "\n");
187         }
188 }
189
190 /** prints a distribution entry */
191 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env)
192 {
193         FILE *dmp_f = env;
194         fprintf(dmp_f, "%12d", cnt_to_uint(&entry->cnt));
195 }
196
197 /**
198  * dumps the distribution of the amount of ready nodes for each block
199  */
200 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
201 {
202         if (pset_count(entry->be_block_hash) > 0) {
203                 be_block_entry_t *b_entry;
204                 int              i;
205
206                 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
207                 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
208                         "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
209
210                 foreach_pset(entry->be_block_hash, b_entry) {
211                         /* this ensures that all keys from 1 to 5 are in the table */
212                         for (i = 1; i < 6; ++i)
213                                 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
214
215                         fprintf(dmp->f, "BLK   %6ld", b_entry->block_nr);
216                         stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp->f);
217                         fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
218                         fprintf(dmp->f, "\n");
219                 }
220         }
221 }
222
223 /**
224  * Adds the counter for given entry to another distribution table.
225  */
226 static void add_distrib_entry(const distrib_entry_t *entry, void *env) {
227         distrib_tbl_t *sum_tbl = env;
228
229         stat_add_int_distrib_tbl(sum_tbl, (int)(entry->object), &entry->cnt);
230 }
231
232 /**
233  * dumps permutation statistics for one and block and one class
234  */
235 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
236 {
237         perm_stat_entry_t *ps_ent;
238         distrib_tbl_t     *sum_chains = stat_new_int_distrib_tbl();
239         distrib_tbl_t     *sum_cycles = stat_new_int_distrib_tbl();
240         char              buf[16];
241         int               i;
242
243         fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
244                 "size",
245                 "real size",
246                 "# chains",
247                 "# cycles",
248                 "# copies",
249                 "# exchanges"
250         );
251
252         foreach_pset(entry->perm_stat, ps_ent) {
253                 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
254                         ps_ent->size,
255                         ps_ent->real_size,
256                         stat_get_count_distrib_tbl(ps_ent->chains),
257                         stat_get_count_distrib_tbl(ps_ent->cycles),
258                         ps_ent->n_copies,
259                         ps_ent->n_exchg
260                 );
261
262                 /* sum up distribution table for chains */
263                 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
264
265                 /* sum up distribution table for cycles */
266                 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
267         }
268
269         /* print chain distribution for all perms of this class in this block */
270         fprintf(dmp->f, "chain distribution:\n");
271
272         /* add all missing entries to chain distribution table */
273         for (i = 1; i <= entry->n_regs; i++) {
274                 snprintf(buf, sizeof(buf), "length %d", i);
275                 fprintf(dmp->f, "%12s", buf);
276                 stat_insert_int_distrib_tbl(sum_chains, i);
277         }
278         fprintf(dmp->f, "\n");
279         stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp->f);
280         fprintf(dmp->f, "\n");
281
282         /* print cycle distribution for all perms of this class in this block */
283         fprintf(dmp->f, "cycle distribution:\n");
284
285         /* add all missing entries to cycle distribution table */
286         for (i = 1; i <= entry->n_regs; i++) {
287                 snprintf(buf, sizeof(buf), "length %d", i);
288                 fprintf(dmp->f, "%12s", buf);
289                 stat_insert_int_distrib_tbl(sum_cycles, i);
290         }
291         fprintf(dmp->f, "\n");
292         stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp->f);
293         fprintf(dmp->f, "\n");
294
295         /* delete temporary sum distribution tables */
296         stat_delete_distrib_tbl(sum_chains);
297         stat_delete_distrib_tbl(sum_cycles);
298
299 }
300
301 /**
302  * dumps statistics about perms
303  */
304 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
305 {
306         if (pset_count(entry->be_block_hash) > 0) {
307                 be_block_entry_t *b_entry;
308
309                 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
310                 foreach_pset(entry->be_block_hash, b_entry) {
311                         perm_class_entry_t *pc_ent;
312
313                         fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
314
315                         if (b_entry->perm_class_stat)
316                                 foreach_pset(b_entry->perm_class_stat, pc_ent) {
317                                         fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
318                                         simple_dump_be_block_permstat_class(dmp, pc_ent);
319                                 }
320                 }
321
322                 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
323         }
324 }
325
326 /**
327  * dumps the number of real_function_call optimization
328  */
329 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
330 {
331         if (! dmp->f)
332                 return;
333
334         if (! cnt_eq(cnt, 0)) {
335                 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
336                 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
337         }
338 }
339
340 /**
341  * dumps the number of tail_recursion optimization
342  */
343 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
344 {
345         if (! dmp->f)
346                 return;
347
348         if (num_tail_recursion > 0) {
349                 fprintf(dmp->f, "\nTail recursion optimized:\n");
350                 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
351         }
352 }
353
354 /**
355  * dumps the edges count
356  */
357 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
358 {
359         if (! dmp->f)
360                 return;
361
362         fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
363 }
364
365 /**
366  * dumps the IRG
367  */
368 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
369 {
370         int i, dump_opts = 1;
371         block_entry_t *b_entry;
372         extbb_entry_t *eb_entry;
373
374         if (! dmp->f)
375                 return;
376
377         if (entry->irg) {
378                 ir_graph *const_irg = get_const_code_irg();
379
380                 if (entry->irg == const_irg)
381                         fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
382                 else {
383                         if (entry->ent)
384                                 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
385                         else
386                                 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
387                 }
388
389                 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
390                         " was inlined               : %u\n"
391                         " got inlined               : %u\n"
392                         " strength red              : %u\n"
393                         " leaf function             : %s\n"
394                         " calls only leaf functions : %s\n"
395                         " recursive                 : %s\n"
396                         " chain call                : %s\n"
397                         " calls                     : %u\n"
398                         " indirect calls            : %u\n",
399                         entry->is_deleted ? "DELETED " : "",
400                         cnt_to_uint(&entry->cnt_walked), cnt_to_uint(&entry->cnt_walked_blocks),
401                         cnt_to_uint(&entry->cnt_was_inlined),
402                         cnt_to_uint(&entry->cnt_got_inlined),
403                         cnt_to_uint(&entry->cnt_strength_red),
404                         entry->is_leaf ? "YES" : "NO",
405                         entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
406                         entry->is_recursive ? "YES" : "NO",
407                         entry->is_chain_call ? "YES" : "NO",
408                         cnt_to_uint(&entry->cnt_all_calls),
409                         cnt_to_uint(&entry->cnt_indirect_calls)
410                 );
411
412                 for (i = 0; i < sizeof(entry->cnt_if_conv)/sizeof(entry->cnt_if_conv[0]); ++i) {
413                         fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt_if_conv[i]));
414                 }
415         }
416         else {
417                 fprintf(dmp->f, "\nGlobals counts:\n");
418                 fprintf(dmp->f, "--------------\n");
419                 dump_opts = 0;
420         }
421
422         simple_dump_opcode_hash(dmp, entry->opcode_hash);
423         simple_dump_edges(dmp, &entry->cnt_edges);
424
425         /* effects of optimizations */
426         if (dump_opts) {
427                 int i;
428
429                 simple_dump_real_func_calls(dmp, &entry->cnt_real_func_call);
430                 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
431
432                 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
433                         simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
434                 }
435
436                 /* dump block info */
437                 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
438                 foreach_pset(entry->block_hash, b_entry) {
439                         fprintf(dmp->f, "BLK   %6ld %12u %12u %12u %12u %12u %4.8f\n",
440                                 b_entry->block_nr,
441                                 cnt_to_uint(&b_entry->cnt_nodes),
442                                 cnt_to_uint(&b_entry->cnt_edges),
443                                 cnt_to_uint(&b_entry->cnt_in_edges),
444                                 cnt_to_uint(&b_entry->cnt_out_edges),
445                                 cnt_to_uint(&b_entry->cnt_phi_data),
446                                 cnt_to_dbl(&b_entry->cnt_edges) / cnt_to_dbl(&b_entry->cnt_nodes)
447                         );
448                 }
449
450                 /* dump block reg pressure */
451                 simple_dump_be_block_reg_pressure(dmp, entry);
452
453                 /* dump block ready nodes distribution */
454                 simple_dump_be_block_sched_ready(dmp, entry);
455
456                 /* dump block permutation statistics */
457                 simple_dump_be_block_permstat(dmp, entry);
458
459                 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
460                         /* dump extended block info */
461                         fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
462                         foreach_pset(entry->extbb_hash, eb_entry) {
463                                 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
464                                         eb_entry->block_nr,
465                                         cnt_to_uint(&eb_entry->cnt_nodes),
466                                         cnt_to_uint(&eb_entry->cnt_edges),
467                                         cnt_to_uint(&eb_entry->cnt_in_edges),
468                                         cnt_to_uint(&eb_entry->cnt_out_edges),
469                                         cnt_to_uint(&eb_entry->cnt_phi_data),
470                                         cnt_to_dbl(&eb_entry->cnt_edges) / cnt_to_dbl(&eb_entry->cnt_nodes)
471                                 );
472                         }
473                 }
474         }
475 }
476
477 /**
478  * dumps the IRG
479  */
480 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
481 {
482         int i;
483         counter_t sum;
484
485         if (! dmp->f)
486                 return;
487
488         cnt_clr(&sum);
489
490         fprintf(dmp->f, "\nConstant Information:\n");
491         fprintf(dmp->f, "---------------------\n");
492
493         fprintf(dmp->f, "\nBit usage for integer constants\n");
494         fprintf(dmp->f, "-------------------------------\n");
495
496         for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
497                 fprintf(dmp->f, "%5d %12u\n", i + 1, cnt_to_uint(&tbl->int_bits_count[i]));
498                 cnt_add(&sum, &tbl->int_bits_count[i]);
499         }
500         fprintf(dmp->f, "-------------------------------\n");
501
502         fprintf(dmp->f, "\nFloating point constants classification\n");
503         fprintf(dmp->f, "--------------------------------------\n");
504         for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
505                 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
506                 cnt_add(&sum, &tbl->floats[i]);
507         }
508         fprintf(dmp->f, "--------------------------------------\n");
509
510         fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
511         cnt_add(&sum, &tbl->others);
512         fprintf(dmp->f, "-------------------------------\n");
513
514         fprintf(dmp->f, "sum   %12u\n", cnt_to_uint(&sum));
515 }
516
517 /**
518  * initialize the simple dumper
519  */
520 static void simple_init(dumper_t *dmp, const char *name)
521 {
522         char fname[2048];
523
524         snprintf(fname, sizeof(fname), "%s.txt", name);
525         dmp->f = fopen(fname, "w");
526         if (! dmp->f) {
527                 perror(fname);
528         }
529 }
530
531 /**
532  * finishes the simple dumper
533  */
534 static void simple_finish(dumper_t *dmp)
535 {
536         if (dmp->f)
537                 fclose(dmp->f);
538         dmp->f = NULL;
539 }
540
541 /**
542  * the simple human readable dumper
543  */
544 const dumper_t simple_dumper = {
545         simple_dump_graph,
546         simple_dump_const_tbl,
547         simple_init,
548         simple_finish,
549         NULL,
550         NULL,
551         NULL,
552         NULL,
553         FOURCC('S', 'M', 'P', 'L'),
554 };
555
556 /* ---------------------------------------------------------------------- */
557
558 /**
559  * count the nodes as needed:
560  *
561  * 1 normal (data) Phi's
562  * 2 memory Phi's
563  * 3 Proj
564  * 0 all other nodes
565  */
566 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
567 {
568         node_entry_t *entry;
569         int i;
570
571         for (i = 0; i < 4; ++i)
572                 cnt_clr(&cnt[i]);
573
574         foreach_pset(graph->opcode_hash, entry) {
575                 if (entry->op == op_Phi) {
576                         /* normal Phi */
577                         cnt_add(&cnt[1], &entry->cnt_alive);
578                 }
579                 else if (entry->op == dmp->status->op_PhiM) {
580                         /* memory Phi */
581                         cnt_add(&cnt[2], &entry->cnt_alive);
582                 }
583                 else if (entry->op == op_Proj) {
584                         /* Proj */
585                         cnt_add(&cnt[3], &entry->cnt_alive);
586                 }
587                 else {
588                         /* all other nodes */
589                         cnt_add(&cnt[0], &entry->cnt_alive);
590                 }
591         }
592 }
593
594 /**
595  * dumps the IRG
596  */
597 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
598 {
599         const char *name;
600         counter_t cnt[4];
601
602         if (! dmp->f)
603                 return;
604
605         if (entry->irg && !entry->is_deleted) {
606                 ir_graph *const_irg = get_const_code_irg();
607
608                 if (entry->irg == const_irg) {
609                         name = "<Const code Irg>";
610                         return;
611                 }
612                 else {
613                         if (entry->ent)
614                                 name = get_entity_name(entry->ent);
615                         else
616                                 name = "<UNKNOWN IRG>";
617                 }
618
619                 csv_count_nodes(dmp, entry, cnt);
620
621                 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
622                         name,
623                         (void *)entry->irg,
624                         cnt_to_uint(&cnt[0]),
625                         cnt_to_uint(&cnt[1]),
626                         cnt_to_uint(&cnt[2]),
627                         cnt_to_uint(&cnt[3])
628                 );
629         }
630 }
631
632 /**
633  * dumps the IRG
634  */
635 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
636 {
637         /* FIXME: NYI */
638 }
639
640 /**
641  * initialize the simple dumper
642  */
643 static void csv_init(dumper_t *dmp, const char *name)
644 {
645         char fname[2048];
646
647         snprintf(fname, sizeof(fname), "%s.csv", name);
648         dmp->f = fopen(fname, "a");
649         if (! dmp->f)
650                 perror(fname);
651 }
652
653 /**
654  * finishes the simple dumper
655  */
656 static void csv_finish(dumper_t *dmp)
657 {
658         if (dmp->f)
659                 fclose(dmp->f);
660         dmp->f = NULL;
661 }
662
663 /**
664  * the simple human readable dumper
665  */
666 const dumper_t csv_dumper = {
667         csv_dump_graph,
668         csv_dump_const_tbl,
669         csv_init,
670         csv_finish,
671         NULL,
672         NULL,
673         NULL,
674         NULL,
675         FOURCC('C', 'S', 'V', '\0')
676 };