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