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