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_CONST_PHI, "constant evaluation on Phi node" },
114 { FS_OPT_PREDICATE, "predicate optimization" },
115 { FS_OPT_DEMORGAN, "optimization using DeMorgan's law" },
116 { FS_OPT_CMP_OP_OP, "CMP optimization: Cmp(OP(x), OP(y)) = Cmp(x, y)" },
117 { FS_OPT_CMP_OP_C, "CMP optimization: Cmp(OP(x), c1) = Cmp(x, c2)" },
118 { FS_OPT_CMP_CONV_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(x, y)" },
119 { FS_OPT_CMP_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(Conv(x), y)" },
120 { FS_OPT_CMP_TO_BOOL, "CMP optimization: Cmp(x, y) = BoolOP(x, y)" },
121 { FS_OPT_CMP_CNST_MAGN, "CMP optimization: reduced magnitude of a const" },
122 { FS_OPT_CMP_SHF_TO_AND, "CMP optimization: transformed shift into And" },
123 { FS_OPT_CMP_MOD_TO_AND, "CMP optimization: transformed Mod into And" },
124 { FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
125 { FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
126 { FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
127 { FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
128 { FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
129 { FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
130 { FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
131 { FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
132 { FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
133 { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
134 { FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
137 static const char *if_conv_names[IF_RESULT_LAST] = {
139 "if conv side effect ",
140 "if conv Phi node found ",
141 "if conv to deep DAG's ",
142 "if conv bad control flow ",
143 "if conv denied by arch ",
147 * dumps a opcode hash into human readable form
149 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
153 counter_t f_new_node;
157 cnt_clr(&f_new_node);
160 fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
161 foreach_pset(set, entry) {
162 fprintf(dmp->f, "%-16s %8u %8u %8u\n",
163 get_id_str(entry->op->name),
164 cnt_to_uint(&entry->cnt_alive),
165 cnt_to_uint(&entry->new_node),
166 cnt_to_uint(&entry->into_Id)
169 cnt_add(&f_alive, &entry->cnt_alive);
170 cnt_add(&f_new_node, &entry->new_node);
171 cnt_add(&f_Id, &entry->into_Id);
173 fprintf(dmp->f, "-------------------------------------------\n");
174 fprintf(dmp->f, "%-16s %8u %8u %8u\n", "Sum",
175 cnt_to_uint(&f_alive),
176 cnt_to_uint(&f_new_node),
179 } /* simple_dump_opcode_hash */
182 * Return the name of an optimization.
184 static const char *get_opt_name(int index) {
185 assert(index < (int) ARR_SIZE(opt_names) && "index out of range");
186 assert((int) opt_names[index].kind == index && "opt_names broken");
187 return opt_names[index].name;
191 * dumps an optimization hash into human readable form
193 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
195 if (pset_count(set) > 0) {
197 const char *name = get_opt_name(index);
199 fprintf(dmp->f, "\n%s:\n", name);
200 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
202 foreach_pset(set, entry) {
203 fprintf(dmp->f, "%-16s %8u\n",
204 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
207 } /* simple_dump_opt_hash */
210 * dumps the register pressure for each block and for each register class
212 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
214 be_block_entry_t *b_entry = pset_first(entry->be_block_hash);
215 reg_pressure_entry_t *rp_entry;
217 /* return if no be statistic information available */
221 fprintf(dmp->f, "\nREG PRESSURE:\n");
222 fprintf(dmp->f, "%12s", "Block Nr");
224 /* print table head (register class names) */
225 foreach_pset(b_entry->reg_pressure, rp_entry)
226 fprintf(dmp->f, "%15s", rp_entry->class_name);
227 fprintf(dmp->f, "\n");
229 /* print the reg pressure for all blocks and register classes */
230 for (/* b_entry is already initialized */ ;
232 b_entry = pset_next(entry->be_block_hash)) {
233 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
235 foreach_pset(b_entry->reg_pressure, rp_entry)
236 fprintf(dmp->f, "%15d", rp_entry->pressure);
237 fprintf(dmp->f, "\n");
239 } /* simple_dump_be_block_reg_pressure */
241 /** prints a distribution entry */
242 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env) {
244 fprintf(dmp->f, "%12d", cnt_to_uint(&entry->cnt));
245 } /* simple_dump_distrib_entry */
248 * dumps the distribution of the amount of ready nodes for each block
250 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
252 if (pset_count(entry->be_block_hash) > 0) {
253 be_block_entry_t *b_entry;
256 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
257 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
258 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
260 foreach_pset(entry->be_block_hash, b_entry) {
261 /* this ensures that all keys from 1 to 5 are in the table */
262 for (i = 1; i < 6; ++i)
263 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
265 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
266 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
267 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
268 fprintf(dmp->f, "\n");
271 } /* simple_dump_be_block_sched_ready */
274 * Adds the counter for given entry to another distribution table.
276 static void add_distrib_entry(const distrib_entry_t *entry, void *env) {
277 distrib_tbl_t *sum_tbl = env;
279 stat_add_int_distrib_tbl(sum_tbl, (int)(entry->object), &entry->cnt);
280 } /* add_distrib_entry */
283 * dumps permutation statistics for one and block and one class
285 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
287 perm_stat_entry_t *ps_ent;
288 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
289 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
293 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
302 foreach_pset(entry->perm_stat, ps_ent) {
303 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
306 stat_get_count_distrib_tbl(ps_ent->chains),
307 stat_get_count_distrib_tbl(ps_ent->cycles),
312 /* sum up distribution table for chains */
313 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
315 /* sum up distribution table for cycles */
316 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
319 /* print chain distribution for all perms of this class in this block */
320 fprintf(dmp->f, "chain distribution:\n");
322 /* add all missing entries to chain distribution table */
323 for (i = 1; i <= entry->n_regs; i++) {
324 snprintf(buf, sizeof(buf), "length %d", i);
325 fprintf(dmp->f, "%12s", buf);
326 stat_insert_int_distrib_tbl(sum_chains, i);
328 fprintf(dmp->f, "\n");
329 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
330 fprintf(dmp->f, "\n");
332 /* print cycle distribution for all perms of this class in this block */
333 fprintf(dmp->f, "cycle distribution:\n");
335 /* add all missing entries to cycle distribution table */
336 for (i = 1; i <= entry->n_regs; i++) {
337 snprintf(buf, sizeof(buf), "length %d", i);
338 fprintf(dmp->f, "%12s", buf);
339 stat_insert_int_distrib_tbl(sum_cycles, i);
341 fprintf(dmp->f, "\n");
342 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
343 fprintf(dmp->f, "\n");
345 /* delete temporary sum distribution tables */
346 stat_delete_distrib_tbl(sum_chains);
347 stat_delete_distrib_tbl(sum_cycles);
349 } /* simple_dump_be_block_permstat_class */
352 * dumps statistics about perms
354 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
356 if (pset_count(entry->be_block_hash) > 0) {
357 be_block_entry_t *b_entry;
359 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
360 foreach_pset(entry->be_block_hash, b_entry) {
361 perm_class_entry_t *pc_ent;
363 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
365 if (b_entry->perm_class_stat) {
366 foreach_pset(b_entry->perm_class_stat, pc_ent) {
367 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
368 simple_dump_be_block_permstat_class(dmp, pc_ent);
373 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
375 } /* simple_dump_be_block_permstat */
378 * dumps the number of real_function_call optimization
380 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
385 if (! cnt_eq(cnt, 0)) {
386 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
387 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
389 } /* simple_dump_real_func_calls */
392 * dumps the number of tail_recursion optimization
394 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
399 if (num_tail_recursion > 0) {
400 fprintf(dmp->f, "\nTail recursion optimized:\n");
401 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
403 } /* simple_dump_tail_recursion */
406 * dumps the edges count
408 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
413 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
414 } /* simple_dump_edges */
419 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
421 int i, dump_opts = 1;
422 block_entry_t *b_entry;
423 extbb_entry_t *eb_entry;
429 ir_graph *const_irg = get_const_code_irg();
431 if (entry->irg == const_irg)
432 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
435 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
437 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
440 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
441 " was inlined : %u\n"
442 " got inlined : %u\n"
443 " strength red : %u\n"
444 " leaf function : %s\n"
445 " calls only leaf functions : %s\n"
449 " indirect calls : %u\n",
450 entry->is_deleted ? "DELETED " : "",
451 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
452 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
453 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
454 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
455 entry->is_leaf ? "YES" : "NO",
456 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
457 entry->is_recursive ? "YES" : "NO",
458 entry->is_chain_call ? "YES" : "NO",
459 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
460 cnt_to_uint(&entry->cnt[gcnt_indirect_calls])
463 for (i = 0; i < IF_RESULT_LAST; ++i) {
464 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
467 fprintf(dmp->f, "\nGlobals counts:\n");
468 fprintf(dmp->f, "--------------\n");
474 " pure address calc ops : %u\n"
475 " all address calc ops : %u\n",
476 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
477 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
480 /* Load/Store address classification */
482 " global Ld/St address : %u\n"
483 " local Ld/St address : %u\n"
484 " this Ld/St address : %u\n"
485 " param Ld/St address : %u\n"
486 " other Ld/St address : %u\n",
487 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
488 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
489 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
490 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
491 cnt_to_uint(&entry->cnt[gcnt_other_adr])
494 simple_dump_opcode_hash(dmp, entry->opcode_hash);
495 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
497 /* effects of optimizations */
501 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
502 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
504 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
505 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
508 /* dump block info */
509 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
510 foreach_pset(entry->block_hash, b_entry) {
511 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f\n",
513 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
514 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
515 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
516 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
517 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
518 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes])
522 /* dump block reg pressure */
523 simple_dump_be_block_reg_pressure(dmp, entry);
525 /* dump block ready nodes distribution */
526 simple_dump_be_block_sched_ready(dmp, entry);
528 /* dump block permutation statistics */
529 simple_dump_be_block_permstat(dmp, entry);
531 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
532 /* dump extended block info */
533 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
534 foreach_pset(entry->extbb_hash, eb_entry) {
535 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
537 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
538 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
539 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
540 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
541 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
542 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
547 } /* simple_dump_graph */
550 * dumps the constant table
552 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
562 fprintf(dmp->f, "\nConstant Information:\n");
563 fprintf(dmp->f, "---------------------\n");
565 fprintf(dmp->f, "\nBit usage for integer constants\n");
566 fprintf(dmp->f, "-------------------------------\n");
568 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
569 fprintf(dmp->f, "%5d %12u\n", i + 1, cnt_to_uint(&tbl->int_bits_count[i]));
570 cnt_add(&sum, &tbl->int_bits_count[i]);
572 fprintf(dmp->f, "-------------------------------\n");
574 fprintf(dmp->f, "\nFloating point constants classification\n");
575 fprintf(dmp->f, "--------------------------------------\n");
576 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
577 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
578 cnt_add(&sum, &tbl->floats[i]);
580 fprintf(dmp->f, "--------------------------------------\n");
582 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
583 cnt_add(&sum, &tbl->others);
584 fprintf(dmp->f, "-------------------------------\n");
586 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
587 } /* simple_dump_const_tbl */
590 * Dumps a line of the parameter table
592 static void dump_tbl_line(const distrib_entry_t *entry, void *env) {
595 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
596 } /* dump_tbl_line */
599 * dumps the parameter distribution table
601 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
602 fprintf(dmp->f, "\nCall parameter Information:\n");
603 fprintf(dmp->f, "---------------------\n");
605 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
606 fprintf(dmp->f, "-------------------------------\n");
608 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
609 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
610 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
611 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
612 } /* simple_dump_param_tbl */
615 * dumps the optimization counter table
617 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
620 fprintf(dmp->f, "\nOptimization counts:\n");
621 fprintf(dmp->f, "---------------------\n");
623 for (i = 0; i < len; ++i) {
624 unsigned cnt = cnt_to_uint(&tbl[i]);
627 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
630 } /* simple_dump_opt_cnt */
633 * initialize the simple dumper
635 static void simple_init(dumper_t *dmp, const char *name) {
638 snprintf(fname, sizeof(fname), "%s.txt", name);
639 dmp->f = fopen(fname, "w");
646 * finishes the simple dumper
648 static void simple_finish(dumper_t *dmp) {
652 } /* simple_finish */
655 * the simple human readable dumper
657 const dumper_t simple_dumper = {
659 simple_dump_const_tbl,
660 simple_dump_param_tbl,
668 FOURCC('S', 'M', 'P', 'L'),
671 /* ---------------------------------------------------------------------- */
674 * count the nodes as needed:
676 * 1 normal (data) Phi's
681 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
686 for (i = 0; i < 4; ++i)
689 foreach_pset(graph->opcode_hash, entry) {
690 if (entry->op == op_Phi) {
692 cnt_add(&cnt[1], &entry->cnt_alive);
693 } else if (entry->op == dmp->status->op_PhiM) {
695 cnt_add(&cnt[2], &entry->cnt_alive);
696 } else if (entry->op == op_Proj) {
698 cnt_add(&cnt[3], &entry->cnt_alive);
700 /* all other nodes */
701 cnt_add(&cnt[0], &entry->cnt_alive);
704 } /* csv_count_nodes */
709 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
717 if (entry->irg && !entry->is_deleted) {
718 ir_graph *const_irg = get_const_code_irg();
720 if (entry->irg == const_irg) {
721 name = "<Const code Irg>";
725 name = get_entity_name(entry->ent);
727 name = "<UNKNOWN IRG>";
730 csv_count_nodes(dmp, entry, cnt);
732 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
735 cnt_to_uint(&cnt[0]),
736 cnt_to_uint(&cnt[1]),
737 cnt_to_uint(&cnt[2]),
741 } /* csv_dump_graph */
746 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
751 } /* csv_dump_const_tbl */
754 * dumps the parameter distribution table
756 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
761 } /* csv_dump_param_tbl */
764 * dumps the optimization counter
766 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
771 } /* csv_dump_opt_cnt */
774 * initialize the simple dumper
776 static void csv_init(dumper_t *dmp, const char *name)
780 snprintf(fname, sizeof(fname), "%s.csv", name);
781 dmp->f = fopen(fname, "a");
787 * finishes the simple dumper
789 static void csv_finish(dumper_t *dmp)
797 * the simple human readable dumper
799 const dumper_t csv_dumper = {
810 FOURCC('C', 'S', 'V', '\0')