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 * dumps an optimization hash into human readable form
184 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, 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");
189 if (pset_count(set) > 0) {
192 fprintf(dmp->f, "\n%s:\n", opt_names[index].name);
193 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
195 foreach_pset(set, entry) {
196 fprintf(dmp->f, "%-16s %8u\n",
197 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
200 } /* simple_dump_opt_hash */
203 * dumps the register pressure for each block and for each register class
205 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
207 be_block_entry_t *b_entry = pset_first(entry->be_block_hash);
208 reg_pressure_entry_t *rp_entry;
210 /* return if no be statistic information available */
214 fprintf(dmp->f, "\nREG PRESSURE:\n");
215 fprintf(dmp->f, "%12s", "Block Nr");
217 /* print table head (register class names) */
218 foreach_pset(b_entry->reg_pressure, rp_entry)
219 fprintf(dmp->f, "%15s", rp_entry->class_name);
220 fprintf(dmp->f, "\n");
222 /* print the reg pressure for all blocks and register classes */
223 for (/* b_entry is already initialized */ ;
225 b_entry = pset_next(entry->be_block_hash)) {
226 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
228 foreach_pset(b_entry->reg_pressure, rp_entry)
229 fprintf(dmp->f, "%15d", rp_entry->pressure);
230 fprintf(dmp->f, "\n");
232 } /* simple_dump_be_block_reg_pressure */
234 /** prints a distribution entry */
235 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env) {
237 fprintf(dmp->f, "%12d", cnt_to_uint(&entry->cnt));
238 } /* simple_dump_distrib_entry */
241 * dumps the distribution of the amount of ready nodes for each block
243 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
245 if (pset_count(entry->be_block_hash) > 0) {
246 be_block_entry_t *b_entry;
249 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
250 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
251 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
253 foreach_pset(entry->be_block_hash, b_entry) {
254 /* this ensures that all keys from 1 to 5 are in the table */
255 for (i = 1; i < 6; ++i)
256 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
258 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
259 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
260 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
261 fprintf(dmp->f, "\n");
264 } /* simple_dump_be_block_sched_ready */
267 * Adds the counter for given entry to another distribution table.
269 static void add_distrib_entry(const distrib_entry_t *entry, void *env) {
270 distrib_tbl_t *sum_tbl = env;
272 stat_add_int_distrib_tbl(sum_tbl, (int)(entry->object), &entry->cnt);
273 } /* add_distrib_entry */
276 * dumps permutation statistics for one and block and one class
278 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
280 perm_stat_entry_t *ps_ent;
281 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
282 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
286 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
295 foreach_pset(entry->perm_stat, ps_ent) {
296 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
299 stat_get_count_distrib_tbl(ps_ent->chains),
300 stat_get_count_distrib_tbl(ps_ent->cycles),
305 /* sum up distribution table for chains */
306 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
308 /* sum up distribution table for cycles */
309 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
312 /* print chain distribution for all perms of this class in this block */
313 fprintf(dmp->f, "chain distribution:\n");
315 /* add all missing entries to chain distribution table */
316 for (i = 1; i <= entry->n_regs; i++) {
317 snprintf(buf, sizeof(buf), "length %d", i);
318 fprintf(dmp->f, "%12s", buf);
319 stat_insert_int_distrib_tbl(sum_chains, i);
321 fprintf(dmp->f, "\n");
322 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
323 fprintf(dmp->f, "\n");
325 /* print cycle distribution for all perms of this class in this block */
326 fprintf(dmp->f, "cycle distribution:\n");
328 /* add all missing entries to cycle distribution table */
329 for (i = 1; i <= entry->n_regs; i++) {
330 snprintf(buf, sizeof(buf), "length %d", i);
331 fprintf(dmp->f, "%12s", buf);
332 stat_insert_int_distrib_tbl(sum_cycles, i);
334 fprintf(dmp->f, "\n");
335 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
336 fprintf(dmp->f, "\n");
338 /* delete temporary sum distribution tables */
339 stat_delete_distrib_tbl(sum_chains);
340 stat_delete_distrib_tbl(sum_cycles);
342 } /* simple_dump_be_block_permstat_class */
345 * dumps statistics about perms
347 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
349 if (pset_count(entry->be_block_hash) > 0) {
350 be_block_entry_t *b_entry;
352 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
353 foreach_pset(entry->be_block_hash, b_entry) {
354 perm_class_entry_t *pc_ent;
356 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
358 if (b_entry->perm_class_stat) {
359 foreach_pset(b_entry->perm_class_stat, pc_ent) {
360 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
361 simple_dump_be_block_permstat_class(dmp, pc_ent);
366 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
368 } /* simple_dump_be_block_permstat */
371 * dumps the number of real_function_call optimization
373 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
378 if (! cnt_eq(cnt, 0)) {
379 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
380 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
382 } /* simple_dump_real_func_calls */
385 * dumps the number of tail_recursion optimization
387 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
392 if (num_tail_recursion > 0) {
393 fprintf(dmp->f, "\nTail recursion optimized:\n");
394 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
396 } /* simple_dump_tail_recursion */
399 * dumps the edges count
401 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
406 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
407 } /* simple_dump_edges */
412 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
414 int i, dump_opts = 1;
415 block_entry_t *b_entry;
416 extbb_entry_t *eb_entry;
422 ir_graph *const_irg = get_const_code_irg();
424 if (entry->irg == const_irg)
425 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
428 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
430 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
433 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
434 " was inlined : %u\n"
435 " got inlined : %u\n"
436 " strength red : %u\n"
437 " leaf function : %s\n"
438 " calls only leaf functions : %s\n"
442 " indirect calls : %u\n",
443 entry->is_deleted ? "DELETED " : "",
444 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
445 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
446 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
447 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
448 entry->is_leaf ? "YES" : "NO",
449 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
450 entry->is_recursive ? "YES" : "NO",
451 entry->is_chain_call ? "YES" : "NO",
452 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
453 cnt_to_uint(&entry->cnt[gcnt_indirect_calls])
456 for (i = 0; i < IF_RESULT_LAST; ++i) {
457 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
460 fprintf(dmp->f, "\nGlobals counts:\n");
461 fprintf(dmp->f, "--------------\n");
467 " pure address calc ops : %u\n"
468 " all address calc ops : %u\n",
469 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
470 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
473 /* Load/Store address classification */
475 " global Ld/St address : %u\n"
476 " local Ld/St address : %u\n"
477 " this Ld/St address : %u\n"
478 " param Ld/St address : %u\n"
479 " other Ld/St address : %u\n",
480 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
481 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
482 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
483 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
484 cnt_to_uint(&entry->cnt[gcnt_other_adr])
487 simple_dump_opcode_hash(dmp, entry->opcode_hash);
488 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
490 /* effects of optimizations */
494 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
495 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
497 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
498 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
501 /* dump block info */
502 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
503 foreach_pset(entry->block_hash, b_entry) {
504 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f\n",
506 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
507 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
508 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
509 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
510 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
511 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes])
515 /* dump block reg pressure */
516 simple_dump_be_block_reg_pressure(dmp, entry);
518 /* dump block ready nodes distribution */
519 simple_dump_be_block_sched_ready(dmp, entry);
521 /* dump block permutation statistics */
522 simple_dump_be_block_permstat(dmp, entry);
524 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
525 /* dump extended block info */
526 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
527 foreach_pset(entry->extbb_hash, eb_entry) {
528 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
530 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
531 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
532 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
533 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
534 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
535 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
540 } /* simple_dump_graph */
543 * dumps the constant table
545 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
555 fprintf(dmp->f, "\nConstant Information:\n");
556 fprintf(dmp->f, "---------------------\n");
558 fprintf(dmp->f, "\nBit usage for integer constants\n");
559 fprintf(dmp->f, "-------------------------------\n");
561 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
562 fprintf(dmp->f, "%5d %12u\n", i + 1, cnt_to_uint(&tbl->int_bits_count[i]));
563 cnt_add(&sum, &tbl->int_bits_count[i]);
565 fprintf(dmp->f, "-------------------------------\n");
567 fprintf(dmp->f, "\nFloating point constants classification\n");
568 fprintf(dmp->f, "--------------------------------------\n");
569 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
570 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
571 cnt_add(&sum, &tbl->floats[i]);
573 fprintf(dmp->f, "--------------------------------------\n");
575 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
576 cnt_add(&sum, &tbl->others);
577 fprintf(dmp->f, "-------------------------------\n");
579 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
580 } /* simple_dump_const_tbl */
583 * Dumps a line of the parameter table
585 static void dump_tbl_line(const distrib_entry_t *entry, void *env) {
588 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
589 } /* dump_tbl_line */
592 * dumps the parameter distribution table
594 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
595 fprintf(dmp->f, "\nCall parameter Information:\n");
596 fprintf(dmp->f, "---------------------\n");
598 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
599 fprintf(dmp->f, "-------------------------------\n");
601 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
602 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
603 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
604 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
605 } /* simple_dump_param_tbl */
608 * initialize the simple dumper
610 static void simple_init(dumper_t *dmp, const char *name) {
613 snprintf(fname, sizeof(fname), "%s.txt", name);
614 dmp->f = fopen(fname, "w");
621 * finishes the simple dumper
623 static void simple_finish(dumper_t *dmp) {
627 } /* simple_finish */
630 * the simple human readable dumper
632 const dumper_t simple_dumper = {
634 simple_dump_const_tbl,
635 simple_dump_param_tbl,
642 FOURCC('S', 'M', 'P', 'L'),
645 /* ---------------------------------------------------------------------- */
648 * count the nodes as needed:
650 * 1 normal (data) Phi's
655 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
660 for (i = 0; i < 4; ++i)
663 foreach_pset(graph->opcode_hash, entry) {
664 if (entry->op == op_Phi) {
666 cnt_add(&cnt[1], &entry->cnt_alive);
667 } else if (entry->op == dmp->status->op_PhiM) {
669 cnt_add(&cnt[2], &entry->cnt_alive);
670 } else if (entry->op == op_Proj) {
672 cnt_add(&cnt[3], &entry->cnt_alive);
674 /* all other nodes */
675 cnt_add(&cnt[0], &entry->cnt_alive);
678 } /* csv_count_nodes */
683 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
691 if (entry->irg && !entry->is_deleted) {
692 ir_graph *const_irg = get_const_code_irg();
694 if (entry->irg == const_irg) {
695 name = "<Const code Irg>";
699 name = get_entity_name(entry->ent);
701 name = "<UNKNOWN IRG>";
704 csv_count_nodes(dmp, entry, cnt);
706 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
709 cnt_to_uint(&cnt[0]),
710 cnt_to_uint(&cnt[1]),
711 cnt_to_uint(&cnt[2]),
715 } /* csv_dump_graph */
720 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
725 } /* csv_dump_const_tbl */
728 * dumps the parameter distribution table
730 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
735 } /* csv_dump_param_tbl */
738 * initialize the simple dumper
740 static void csv_init(dumper_t *dmp, const char *name)
744 snprintf(fname, sizeof(fname), "%s.csv", name);
745 dmp->f = fopen(fname, "a");
751 * finishes the simple dumper
753 static void csv_finish(dumper_t *dmp)
761 * the simple human readable dumper
763 const dumper_t csv_dumper = {
773 FOURCC('C', 'S', 'V', '\0')