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