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