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