rename type entity into ir_entity
[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_OPT_CONST_PHI,      "constant evaluation on Phi node" },
81         { FS_BE_IA32_LEA,        "ia32 Backend transformation: Lea was created" },
82         { FS_BE_IA32_LOAD_LEA,   "ia32 Backend transformation: Load merged with a Lea" },
83         { FS_BE_IA32_STORE_LEA,  "ia32 Backend transformation: Store merged with a Lea" },
84         { FS_BE_IA32_AM_S,       "ia32 Backend transformation: Source address mode node created" },
85         { FS_BE_IA32_AM_D,       "ia32 Backend transformation: Destination address mode node created" },
86         { FS_BE_IA32_CJMP,       "ia32 Backend transformation: CJmp created to save a cmp/test" },
87         { FS_BE_IA32_2ADDRCPY,   "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
88         { FS_BE_IA32_SPILL2ST,   "ia32 Backend transformation: Created Store for a Spill" },
89         { FS_BE_IA32_RELOAD2LD,  "ia32 Backend transformation: Created Load for a Reload" },
90         { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
91         { FS_BE_IA32_LEA2ADD,    "ia32 Backend transformation: Transformed Lea back into Add" },
92 };
93
94 static const char *if_conv_names[IF_RESULT_LAST] = {
95         "if conv done             ",
96         "if conv side effect      ",
97         "if conv Phi node found   ",
98         "if conv to deep DAG's    ",
99         "if conv bad control flow ",
100         "if conv denied by arch   ",
101 };
102
103 /**
104  * dumps a opcode hash into human readable form
105  */
106 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
107 {
108         node_entry_t *entry;
109         counter_t f_alive;
110         counter_t f_new_node;
111         counter_t f_Id;
112
113         cnt_clr(&f_alive);
114         cnt_clr(&f_new_node);
115         cnt_clr(&f_Id);
116
117         fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
118         foreach_pset(set, entry) {
119                 fprintf(dmp->f, "%-16s %8u %8u %8u\n",
120                         get_id_str(entry->op->name),
121                         cnt_to_uint(&entry->cnt_alive),
122                         cnt_to_uint(&entry->new_node),
123                         cnt_to_uint(&entry->into_Id)
124                 );
125
126                 cnt_add(&f_alive,    &entry->cnt_alive);
127                 cnt_add(&f_new_node, &entry->new_node);
128                 cnt_add(&f_Id,       &entry->into_Id);
129         }  /* foreach_pset */
130         fprintf(dmp->f, "-------------------------------------------\n");
131         fprintf(dmp->f, "%-16s %8u %8u %8u\n", "Sum",
132                 cnt_to_uint(&f_alive),
133                 cnt_to_uint(&f_new_node),
134                 cnt_to_uint(&f_Id)
135         );
136 }  /* simple_dump_opcode_hash */
137
138 /**
139  * dumps an optimization hash into human readable form
140  */
141 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
142 {
143         assert(index < ARR_SIZE(opt_names) && "index out of range");
144         assert(opt_names[index].kind == index && "opt_names broken");
145
146         if (pset_count(set) > 0) {
147                 opt_entry_t *entry;
148
149                 fprintf(dmp->f, "\n%s:\n", opt_names[index].name);
150                 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
151
152                 foreach_pset(set, entry) {
153                         fprintf(dmp->f, "%-16s %8u\n",
154                                 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
155                 }  /* foreach_pset */
156         }  /* if */
157 }  /* simple_dump_opt_hash */
158
159 /**
160  * dumps the register pressure for each block and for each register class
161  */
162 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
163 {
164         be_block_entry_t     *b_entry = pset_first(entry->be_block_hash);
165         reg_pressure_entry_t *rp_entry;
166
167         /* return if no be statistic information available */
168         if (! b_entry)
169                 return;
170
171         fprintf(dmp->f, "\nREG PRESSURE:\n");
172         fprintf(dmp->f, "%12s", "Block Nr");
173
174         /* print table head (register class names) */
175         foreach_pset(b_entry->reg_pressure, rp_entry)
176                 fprintf(dmp->f, "%15s", rp_entry->class_name);
177         fprintf(dmp->f, "\n");
178
179         /* print the reg pressure for all blocks and register classes */
180         for (/* b_entry is already initialized */ ;
181              b_entry;
182              b_entry = pset_next(entry->be_block_hash)) {
183                 fprintf(dmp->f, "BLK   %6ld", b_entry->block_nr);
184
185                 foreach_pset(b_entry->reg_pressure, rp_entry)
186                         fprintf(dmp->f, "%15d", rp_entry->pressure);
187                 fprintf(dmp->f, "\n");
188         }  /* for */
189 }  /* simple_dump_be_block_reg_pressure */
190
191 /** prints a distribution entry */
192 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env) {
193         FILE *dmp_f = env;
194         fprintf(dmp_f, "%12d", cnt_to_uint(&entry->cnt));
195 }  /* simple_dump_distrib_entry */
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                 }  /* foreach_pset */
220         }  /* if */
221 }  /* simple_dump_be_block_sched_ready */
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 }  /* add_distrib_entry */
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         }  /* foreach_pset */
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         }  /* for */
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         }  /* for */
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 }  /* simple_dump_be_block_permstat_class */
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                                 }  /* foreach_pset */
320                         }  /* if */
321                 }  /* foreach_pset */
322
323                 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
324         }  /* if */
325 }  /* simple_dump_be_block_permstat */
326
327 /**
328  * dumps the number of real_function_call optimization
329  */
330 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
331 {
332         if (! dmp->f)
333                 return;
334
335         if (! cnt_eq(cnt, 0)) {
336                 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
337                 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
338         }  /* if */
339 }  /* simple_dump_real_func_calls */
340
341 /**
342  * dumps the number of tail_recursion optimization
343  */
344 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
345 {
346         if (! dmp->f)
347                 return;
348
349         if (num_tail_recursion > 0) {
350                 fprintf(dmp->f, "\nTail recursion optimized:\n");
351                 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
352         }  /* if */
353 }  /* simple_dump_tail_recursion */
354
355 /**
356  * dumps the edges count
357  */
358 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
359 {
360         if (! dmp->f)
361                 return;
362
363         fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
364 }  /* simple_dump_edges */
365
366 /**
367  * dumps the IRG
368  */
369 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
370 {
371         int i, dump_opts = 1;
372         block_entry_t *b_entry;
373         extbb_entry_t *eb_entry;
374
375         if (! dmp->f)
376                 return;
377
378         if (entry->irg) {
379                 ir_graph *const_irg = get_const_code_irg();
380
381                 if (entry->irg == const_irg)
382                         fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
383                 else {
384                         if (entry->ent)
385                                 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
386                         else
387                                 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
388                 }  /* if */
389
390                 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
391                         " was inlined               : %u\n"
392                         " got inlined               : %u\n"
393                         " strength red              : %u\n"
394                         " leaf function             : %s\n"
395                         " calls only leaf functions : %s\n"
396                         " recursive                 : %s\n"
397                         " chain call                : %s\n"
398                         " calls                     : %u\n"
399                         " indirect calls            : %u\n",
400                         entry->is_deleted ? "DELETED " : "",
401                         cnt_to_uint(&entry->cnt_walked), cnt_to_uint(&entry->cnt_walked_blocks),
402                         cnt_to_uint(&entry->cnt_was_inlined),
403                         cnt_to_uint(&entry->cnt_got_inlined),
404                         cnt_to_uint(&entry->cnt_strength_red),
405                         entry->is_leaf ? "YES" : "NO",
406                         entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
407                         entry->is_recursive ? "YES" : "NO",
408                         entry->is_chain_call ? "YES" : "NO",
409                         cnt_to_uint(&entry->cnt_all_calls),
410                         cnt_to_uint(&entry->cnt_indirect_calls)
411                 );
412
413                 for (i = 0; i < sizeof(entry->cnt_if_conv)/sizeof(entry->cnt_if_conv[0]); ++i) {
414                         fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt_if_conv[i]));
415                 }  /* for */
416         } else {
417                 fprintf(dmp->f, "\nGlobals counts:\n");
418                 fprintf(dmp->f, "--------------\n");
419                 dump_opts = 0;
420         }  /* if */
421
422         /* address ops */
423         fprintf(dmp->f,
424                 " pure address calc ops     : %u\n"
425                 " all address calc ops      : %u\n",
426                 cnt_to_uint(&entry->cnt_pure_adr_ops),
427                 cnt_to_uint(&entry->cnt_all_adr_ops));
428
429         simple_dump_opcode_hash(dmp, entry->opcode_hash);
430         simple_dump_edges(dmp, &entry->cnt_edges);
431
432         /* effects of optimizations */
433         if (dump_opts) {
434                 int i;
435
436                 simple_dump_real_func_calls(dmp, &entry->cnt_real_func_call);
437                 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
438
439                 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
440                         simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
441                 }  /* for */
442
443                 /* dump block info */
444                 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
445                 foreach_pset(entry->block_hash, b_entry) {
446                         fprintf(dmp->f, "BLK   %6ld %12u %12u %12u %12u %12u %4.8f\n",
447                                 b_entry->block_nr,
448                                 cnt_to_uint(&b_entry->cnt_nodes),
449                                 cnt_to_uint(&b_entry->cnt_edges),
450                                 cnt_to_uint(&b_entry->cnt_in_edges),
451                                 cnt_to_uint(&b_entry->cnt_out_edges),
452                                 cnt_to_uint(&b_entry->cnt_phi_data),
453                                 cnt_to_dbl(&b_entry->cnt_edges) / cnt_to_dbl(&b_entry->cnt_nodes)
454                         );
455                 }  /* foreach_pset */
456
457                 /* dump block reg pressure */
458                 simple_dump_be_block_reg_pressure(dmp, entry);
459
460                 /* dump block ready nodes distribution */
461                 simple_dump_be_block_sched_ready(dmp, entry);
462
463                 /* dump block permutation statistics */
464                 simple_dump_be_block_permstat(dmp, entry);
465
466                 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
467                         /* dump extended block info */
468                         fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
469                         foreach_pset(entry->extbb_hash, eb_entry) {
470                                 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
471                                         eb_entry->block_nr,
472                                         cnt_to_uint(&eb_entry->cnt_nodes),
473                                         cnt_to_uint(&eb_entry->cnt_edges),
474                                         cnt_to_uint(&eb_entry->cnt_in_edges),
475                                         cnt_to_uint(&eb_entry->cnt_out_edges),
476                                         cnt_to_uint(&eb_entry->cnt_phi_data),
477                                         cnt_to_dbl(&eb_entry->cnt_edges) / cnt_to_dbl(&eb_entry->cnt_nodes)
478                                 );
479                         }  /* foreach_pset */
480                 }  /* if */
481         }
482 }  /* simple_dump_graph */
483
484 /**
485  * dumps the constant table
486  */
487 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
488 {
489         int i;
490         counter_t sum;
491
492         if (! dmp->f)
493                 return;
494
495         cnt_clr(&sum);
496
497         fprintf(dmp->f, "\nConstant Information:\n");
498         fprintf(dmp->f, "---------------------\n");
499
500         fprintf(dmp->f, "\nBit usage for integer constants\n");
501         fprintf(dmp->f, "-------------------------------\n");
502
503         for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
504                 fprintf(dmp->f, "%5d %12u\n", i + 1, cnt_to_uint(&tbl->int_bits_count[i]));
505                 cnt_add(&sum, &tbl->int_bits_count[i]);
506         }  /* for */
507         fprintf(dmp->f, "-------------------------------\n");
508
509         fprintf(dmp->f, "\nFloating point constants classification\n");
510         fprintf(dmp->f, "--------------------------------------\n");
511         for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
512                 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
513                 cnt_add(&sum, &tbl->floats[i]);
514         }  /* for */
515         fprintf(dmp->f, "--------------------------------------\n");
516
517         fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
518         cnt_add(&sum, &tbl->others);
519         fprintf(dmp->f, "-------------------------------\n");
520
521         fprintf(dmp->f, "sum   %12u\n", cnt_to_uint(&sum));
522 }  /* simple_dump_const_tbl */
523
524 /**
525  * initialize the simple dumper
526  */
527 static void simple_init(dumper_t *dmp, const char *name) {
528         char fname[2048];
529
530         snprintf(fname, sizeof(fname), "%s.txt", name);
531         dmp->f = fopen(fname, "w");
532         if (! dmp->f) {
533                 perror(fname);
534         }  /* if */
535 }  /* simple_init */
536
537 /**
538  * finishes the simple dumper
539  */
540 static void simple_finish(dumper_t *dmp) {
541         if (dmp->f)
542                 fclose(dmp->f);
543         dmp->f = NULL;
544 }  /* simple_finish */
545
546 /**
547  * the simple human readable dumper
548  */
549 const dumper_t simple_dumper = {
550         simple_dump_graph,
551         simple_dump_const_tbl,
552         simple_init,
553         simple_finish,
554         NULL,
555         NULL,
556         NULL,
557         NULL,
558         FOURCC('S', 'M', 'P', 'L'),
559 };
560
561 /* ---------------------------------------------------------------------- */
562
563 /**
564  * count the nodes as needed:
565  *
566  * 1 normal (data) Phi's
567  * 2 memory Phi's
568  * 3 Proj
569  * 0 all other nodes
570  */
571 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
572 {
573         node_entry_t *entry;
574         int i;
575
576         for (i = 0; i < 4; ++i)
577                 cnt_clr(&cnt[i]);
578
579         foreach_pset(graph->opcode_hash, entry) {
580                 if (entry->op == op_Phi) {
581                         /* normal Phi */
582                         cnt_add(&cnt[1], &entry->cnt_alive);
583                 } else if (entry->op == dmp->status->op_PhiM) {
584                         /* memory Phi */
585                         cnt_add(&cnt[2], &entry->cnt_alive);
586                 } else if (entry->op == op_Proj) {
587                         /* Proj */
588                         cnt_add(&cnt[3], &entry->cnt_alive);
589                 } else {
590                         /* all other nodes */
591                         cnt_add(&cnt[0], &entry->cnt_alive);
592                 }  /* if */
593         }  /* foreach_pset */
594 }  /* csv_count_nodes */
595
596 /**
597  * dumps the IRG
598  */
599 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
600 {
601         const char *name;
602         counter_t cnt[4];
603
604         if (! dmp->f)
605                 return;
606
607         if (entry->irg && !entry->is_deleted) {
608                 ir_graph *const_irg = get_const_code_irg();
609
610                 if (entry->irg == const_irg) {
611                         name = "<Const code Irg>";
612                         return;
613                 } else {
614                         if (entry->ent)
615                                 name = get_entity_name(entry->ent);
616                         else
617                                 name = "<UNKNOWN IRG>";
618                 }  /* if */
619
620                 csv_count_nodes(dmp, entry, cnt);
621
622                 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
623                         name,
624                         (void *)entry->irg,
625                         cnt_to_uint(&cnt[0]),
626                         cnt_to_uint(&cnt[1]),
627                         cnt_to_uint(&cnt[2]),
628                         cnt_to_uint(&cnt[3])
629                 );
630         }  /* if */
631 }  /* csv_dump_graph */
632
633 /**
634  * dumps the IRG
635  */
636 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
637 {
638         /* FIXME: NYI */
639 }  /* csv_dump_const_tbl */
640
641 /**
642  * initialize the simple dumper
643  */
644 static void csv_init(dumper_t *dmp, const char *name)
645 {
646         char fname[2048];
647
648         snprintf(fname, sizeof(fname), "%s.csv", name);
649         dmp->f = fopen(fname, "a");
650         if (! dmp->f)
651                 perror(fname);
652 }  /* csv_init */
653
654 /**
655  * finishes the simple dumper
656  */
657 static void csv_finish(dumper_t *dmp)
658 {
659         if (dmp->f)
660                 fclose(dmp->f);
661         dmp->f = NULL;
662 }  /* csv_finish */
663
664 /**
665  * the simple human readable dumper
666  */
667 const dumper_t csv_dumper = {
668         csv_dump_graph,
669         csv_dump_const_tbl,
670         csv_init,
671         csv_finish,
672         NULL,
673         NULL,
674         NULL,
675         NULL,
676         FOURCC('C', 'S', 'V', '\0')
677 };