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