2 * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
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.
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.
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
22 * @brief Statistics for Firm. Dumping.
23 * @author Michael Beck
35 * names of the optimizations
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_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
126 { FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
127 { FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
128 { FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
129 { FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
130 { FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
131 { FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
132 { FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
133 { FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
134 { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
135 { FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
138 static const char *if_conv_names[IF_RESULT_LAST] = {
140 "if conv side effect ",
141 "if conv Phi node found ",
142 "if conv to deep DAG's ",
143 "if conv bad control flow ",
144 "if conv denied by arch ",
148 * dumps a opcode hash into human readable form
150 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
154 counter_t f_new_node;
158 cnt_clr(&f_new_node);
161 fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
162 foreach_pset(set, entry) {
163 fprintf(dmp->f, "%-16s %8u %8u %8u\n",
164 get_id_str(entry->op->name),
165 cnt_to_uint(&entry->cnt_alive),
166 cnt_to_uint(&entry->new_node),
167 cnt_to_uint(&entry->into_Id)
170 cnt_add(&f_alive, &entry->cnt_alive);
171 cnt_add(&f_new_node, &entry->new_node);
172 cnt_add(&f_Id, &entry->into_Id);
174 fprintf(dmp->f, "-------------------------------------------\n");
175 fprintf(dmp->f, "%-16s %8u %8u %8u\n", "Sum",
176 cnt_to_uint(&f_alive),
177 cnt_to_uint(&f_new_node),
180 } /* simple_dump_opcode_hash */
183 * Return the name of an optimization.
185 static const char *get_opt_name(int index) {
186 assert(index < (int) ARR_SIZE(opt_names) && "index out of range");
187 assert((int) opt_names[index].kind == index && "opt_names broken");
188 return opt_names[index].name;
192 * dumps an optimization hash into human readable form
194 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
196 if (pset_count(set) > 0) {
198 const char *name = get_opt_name(index);
200 fprintf(dmp->f, "\n%s:\n", name);
201 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
203 foreach_pset(set, entry) {
204 fprintf(dmp->f, "%-16s %8u\n",
205 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
208 } /* simple_dump_opt_hash */
211 * dumps the register pressure for each block and for each register class
213 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
215 be_block_entry_t *b_entry = pset_first(entry->be_block_hash);
216 reg_pressure_entry_t *rp_entry;
218 /* return if no be statistic information available */
222 fprintf(dmp->f, "\nREG PRESSURE:\n");
223 fprintf(dmp->f, "%12s", "Block Nr");
225 /* print table head (register class names) */
226 foreach_pset(b_entry->reg_pressure, rp_entry)
227 fprintf(dmp->f, "%15s", rp_entry->class_name);
228 fprintf(dmp->f, "\n");
230 /* print the reg pressure for all blocks and register classes */
231 for (/* b_entry is already initialized */ ;
233 b_entry = pset_next(entry->be_block_hash)) {
234 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
236 foreach_pset(b_entry->reg_pressure, rp_entry)
237 fprintf(dmp->f, "%15d", rp_entry->pressure);
238 fprintf(dmp->f, "\n");
240 } /* simple_dump_be_block_reg_pressure */
242 /** prints a distribution entry */
243 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env) {
245 fprintf(dmp->f, "%12d", cnt_to_uint(&entry->cnt));
246 } /* simple_dump_distrib_entry */
249 * dumps the distribution of the amount of ready nodes for each block
251 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
253 if (pset_count(entry->be_block_hash) > 0) {
254 be_block_entry_t *b_entry;
257 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
258 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
259 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
261 foreach_pset(entry->be_block_hash, b_entry) {
262 /* this ensures that all keys from 1 to 5 are in the table */
263 for (i = 1; i < 6; ++i)
264 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
266 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
267 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
268 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
269 fprintf(dmp->f, "\n");
272 } /* simple_dump_be_block_sched_ready */
275 * Adds the counter for given entry to another distribution table.
277 static void add_distrib_entry(const distrib_entry_t *entry, void *env) {
278 distrib_tbl_t *sum_tbl = env;
280 stat_add_int_distrib_tbl(sum_tbl, (int)(entry->object), &entry->cnt);
281 } /* add_distrib_entry */
284 * dumps permutation statistics for one and block and one class
286 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
288 perm_stat_entry_t *ps_ent;
289 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
290 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
294 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
303 foreach_pset(entry->perm_stat, ps_ent) {
304 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
307 stat_get_count_distrib_tbl(ps_ent->chains),
308 stat_get_count_distrib_tbl(ps_ent->cycles),
313 /* sum up distribution table for chains */
314 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
316 /* sum up distribution table for cycles */
317 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
320 /* print chain distribution for all perms of this class in this block */
321 fprintf(dmp->f, "chain distribution:\n");
323 /* add all missing entries to chain distribution table */
324 for (i = 1; i <= entry->n_regs; i++) {
325 snprintf(buf, sizeof(buf), "length %d", i);
326 fprintf(dmp->f, "%12s", buf);
327 stat_insert_int_distrib_tbl(sum_chains, i);
329 fprintf(dmp->f, "\n");
330 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
331 fprintf(dmp->f, "\n");
333 /* print cycle distribution for all perms of this class in this block */
334 fprintf(dmp->f, "cycle distribution:\n");
336 /* add all missing entries to cycle distribution table */
337 for (i = 1; i <= entry->n_regs; i++) {
338 snprintf(buf, sizeof(buf), "length %d", i);
339 fprintf(dmp->f, "%12s", buf);
340 stat_insert_int_distrib_tbl(sum_cycles, i);
342 fprintf(dmp->f, "\n");
343 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
344 fprintf(dmp->f, "\n");
346 /* delete temporary sum distribution tables */
347 stat_delete_distrib_tbl(sum_chains);
348 stat_delete_distrib_tbl(sum_cycles);
350 } /* simple_dump_be_block_permstat_class */
353 * dumps statistics about perms
355 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
357 if (pset_count(entry->be_block_hash) > 0) {
358 be_block_entry_t *b_entry;
360 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
361 foreach_pset(entry->be_block_hash, b_entry) {
362 perm_class_entry_t *pc_ent;
364 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
366 if (b_entry->perm_class_stat) {
367 foreach_pset(b_entry->perm_class_stat, pc_ent) {
368 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
369 simple_dump_be_block_permstat_class(dmp, pc_ent);
374 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
376 } /* simple_dump_be_block_permstat */
379 * dumps the number of real_function_call optimization
381 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
386 if (! cnt_eq(cnt, 0)) {
387 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
388 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
390 } /* simple_dump_real_func_calls */
393 * dumps the number of tail_recursion optimization
395 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
400 if (num_tail_recursion > 0) {
401 fprintf(dmp->f, "\nTail recursion optimized:\n");
402 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
404 } /* simple_dump_tail_recursion */
407 * dumps the edges count
409 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
414 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
415 } /* simple_dump_edges */
420 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
422 int i, dump_opts = 1;
423 block_entry_t *b_entry;
424 extbb_entry_t *eb_entry;
430 ir_graph *const_irg = get_const_code_irg();
432 if (entry->irg == const_irg)
433 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
436 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
438 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
441 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
442 " was inlined : %u\n"
443 " got inlined : %u\n"
444 " strength red : %u\n"
445 " leaf function : %s\n"
446 " calls only leaf functions : %s\n"
450 " indirect calls : %u\n",
451 entry->is_deleted ? "DELETED " : "",
452 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
453 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
454 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
455 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
456 entry->is_leaf ? "YES" : "NO",
457 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
458 entry->is_recursive ? "YES" : "NO",
459 entry->is_chain_call ? "YES" : "NO",
460 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
461 cnt_to_uint(&entry->cnt[gcnt_indirect_calls])
464 for (i = 0; i < IF_RESULT_LAST; ++i) {
465 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
468 fprintf(dmp->f, "\nGlobals counts:\n");
469 fprintf(dmp->f, "--------------\n");
475 " pure address calc ops : %u\n"
476 " all address calc ops : %u\n",
477 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
478 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
481 /* Load/Store address classification */
483 " global Ld/St address : %u\n"
484 " local Ld/St address : %u\n"
485 " this Ld/St address : %u\n"
486 " param Ld/St address : %u\n"
487 " other Ld/St address : %u\n",
488 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
489 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
490 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
491 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
492 cnt_to_uint(&entry->cnt[gcnt_other_adr])
495 simple_dump_opcode_hash(dmp, entry->opcode_hash);
496 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
498 /* effects of optimizations */
502 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
503 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
505 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
506 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
509 /* dump block info */
510 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
511 foreach_pset(entry->block_hash, b_entry) {
512 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f\n",
514 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
515 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
516 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
517 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
518 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
519 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes])
523 /* dump block reg pressure */
524 simple_dump_be_block_reg_pressure(dmp, entry);
526 /* dump block ready nodes distribution */
527 simple_dump_be_block_sched_ready(dmp, entry);
529 /* dump block permutation statistics */
530 simple_dump_be_block_permstat(dmp, entry);
532 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
533 /* dump extended block info */
534 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
535 foreach_pset(entry->extbb_hash, eb_entry) {
536 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
538 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
539 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
540 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
541 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
542 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
543 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
548 } /* simple_dump_graph */
551 * dumps the constant table
553 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
563 fprintf(dmp->f, "\nConstant Information:\n");
564 fprintf(dmp->f, "---------------------\n");
566 fprintf(dmp->f, "\nBit usage for integer constants\n");
567 fprintf(dmp->f, "-------------------------------\n");
569 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
570 fprintf(dmp->f, "%5d %12u\n", i + 1, cnt_to_uint(&tbl->int_bits_count[i]));
571 cnt_add(&sum, &tbl->int_bits_count[i]);
573 fprintf(dmp->f, "-------------------------------\n");
575 fprintf(dmp->f, "\nFloating point constants classification\n");
576 fprintf(dmp->f, "--------------------------------------\n");
577 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
578 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
579 cnt_add(&sum, &tbl->floats[i]);
581 fprintf(dmp->f, "--------------------------------------\n");
583 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
584 cnt_add(&sum, &tbl->others);
585 fprintf(dmp->f, "-------------------------------\n");
587 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
588 } /* simple_dump_const_tbl */
591 * Dumps a line of the parameter table
593 static void dump_tbl_line(const distrib_entry_t *entry, void *env) {
596 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
597 } /* dump_tbl_line */
600 * dumps the parameter distribution table
602 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
603 fprintf(dmp->f, "\nCall parameter Information:\n");
604 fprintf(dmp->f, "---------------------\n");
606 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
607 fprintf(dmp->f, "-------------------------------\n");
609 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
610 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
611 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
612 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
613 } /* simple_dump_param_tbl */
616 * dumps the optimization counter table
618 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
621 fprintf(dmp->f, "\nOptimization counts:\n");
622 fprintf(dmp->f, "---------------------\n");
624 for (i = 0; i < len; ++i) {
625 unsigned cnt = cnt_to_uint(&tbl[i]);
628 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
631 } /* simple_dump_opt_cnt */
634 * initialize the simple dumper
636 static void simple_init(dumper_t *dmp, const char *name) {
639 snprintf(fname, sizeof(fname), "%s.txt", name);
640 dmp->f = fopen(fname, "w");
647 * finishes the simple dumper
649 static void simple_finish(dumper_t *dmp) {
653 } /* simple_finish */
656 * the simple human readable dumper
658 const dumper_t simple_dumper = {
660 simple_dump_const_tbl,
661 simple_dump_param_tbl,
669 FOURCC('S', 'M', 'P', 'L'),
672 /* ---------------------------------------------------------------------- */
675 * count the nodes as needed:
677 * 1 normal (data) Phi's
682 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
687 for (i = 0; i < 4; ++i)
690 foreach_pset(graph->opcode_hash, entry) {
691 if (entry->op == op_Phi) {
693 cnt_add(&cnt[1], &entry->cnt_alive);
694 } else if (entry->op == dmp->status->op_PhiM) {
696 cnt_add(&cnt[2], &entry->cnt_alive);
697 } else if (entry->op == op_Proj) {
699 cnt_add(&cnt[3], &entry->cnt_alive);
701 /* all other nodes */
702 cnt_add(&cnt[0], &entry->cnt_alive);
705 } /* csv_count_nodes */
710 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
718 if (entry->irg && !entry->is_deleted) {
719 ir_graph *const_irg = get_const_code_irg();
721 if (entry->irg == const_irg) {
722 name = "<Const code Irg>";
726 name = get_entity_name(entry->ent);
728 name = "<UNKNOWN IRG>";
731 csv_count_nodes(dmp, entry, cnt);
733 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
736 cnt_to_uint(&cnt[0]),
737 cnt_to_uint(&cnt[1]),
738 cnt_to_uint(&cnt[2]),
742 } /* csv_dump_graph */
747 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
752 } /* csv_dump_const_tbl */
755 * dumps the parameter distribution table
757 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
762 } /* csv_dump_param_tbl */
765 * dumps the optimization counter
767 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
772 } /* csv_dump_opt_cnt */
775 * initialize the simple dumper
777 static void csv_init(dumper_t *dmp, const char *name)
781 snprintf(fname, sizeof(fname), "%s.csv", name);
782 dmp->f = fopen(fname, "a");
788 * finishes the simple dumper
790 static void csv_finish(dumper_t *dmp)
798 * the simple human readable dumper
800 const dumper_t csv_dumper = {
811 FOURCC('C', 'S', 'V', '\0')