2 * Copyright (C) 1995-2008 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_OPT_RTS_ABS, "RTS optimization: call to abs() replaced" },
126 { FS_OPT_RTS_ALLOCA, "RTS optimization: call to alloca() replaced" },
127 { FS_OPT_RTS_SQRT, "RTS optimization: call to sqrt() replaced" },
128 { FS_OPT_RTS_CBRT, "RTS optimization: call to cbrt() replaced" },
129 { FS_OPT_RTS_POW, "RTS optimization: call to pow() replaced" },
130 { FS_OPT_RTS_EXP, "RTS optimization: call to exp() replaced" },
131 { FS_OPT_RTS_LOG, "RTS optimization: call to log() replaced" },
132 { FS_OPT_RTS_SIN, "RTS optimization: call to sin() replaced" },
133 { FS_OPT_RTS_COS, "RTS optimization: call to cos() replaced" },
134 { FS_OPT_RTS_TAN, "RTS optimization: call to tan() replaced" },
135 { FS_OPT_RTS_ASIN, "RTS optimization: call to asin() replaced" },
136 { FS_OPT_RTS_ACOS, "RTS optimization: call to atan() replaced" },
137 { FS_OPT_RTS_ATAN, "RTS optimization: call to acos() replaced" },
138 { FS_OPT_RTS_SINH, "RTS optimization: call to sinh() replaced" },
139 { FS_OPT_RTS_COSH, "RTS optimization: call to cosh() replaced" },
140 { FS_OPT_RTS_TANH, "RTS optimization: call to tanh() replaced" },
141 { FS_OPT_RTS_STRCMP, "RTS optimization: call to strcmp() replaced" },
142 { FS_OPT_RTS_STRNCMP, "RTS optimization: call to strncmp() replaced" },
143 { FS_OPT_RTS_MEMCPY, "RTS optimization: call to memcpy() replaced" },
144 { FS_OPT_RTS_MEMSET, "RTS optimization: call to memset() replaced" },
145 { FS_OPT_RTS_STRLEN, "RTS optimization: call to strlen() replaced" },
146 { FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
147 { FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
148 { FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
149 { FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
150 { FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
151 { FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
152 { FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
153 { FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
154 { FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
155 { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
156 { FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
159 static const char *if_conv_names[IF_RESULT_LAST] = {
161 "if conv side effect ",
162 "if conv Phi node found ",
163 "if conv to deep DAG's ",
164 "if conv bad control flow ",
165 "if conv denied by arch ",
169 * dumps a opcode hash into human readable form
171 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
175 counter_t f_new_node;
179 cnt_clr(&f_new_node);
182 fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
183 foreach_pset(set, entry) {
184 fprintf(dmp->f, "%-16s %8u %8u %8u\n",
185 get_id_str(entry->op->name),
186 cnt_to_uint(&entry->cnt_alive),
187 cnt_to_uint(&entry->new_node),
188 cnt_to_uint(&entry->into_Id)
191 cnt_add(&f_alive, &entry->cnt_alive);
192 cnt_add(&f_new_node, &entry->new_node);
193 cnt_add(&f_Id, &entry->into_Id);
195 fprintf(dmp->f, "-------------------------------------------\n");
196 fprintf(dmp->f, "%-16s %8u %8u %8u\n", "Sum",
197 cnt_to_uint(&f_alive),
198 cnt_to_uint(&f_new_node),
201 } /* simple_dump_opcode_hash */
204 * Return the name of an optimization.
206 static const char *get_opt_name(int index) {
207 assert(index < (int) ARR_SIZE(opt_names) && "index out of range");
208 assert((int) opt_names[index].kind == index && "opt_names broken");
209 return opt_names[index].name;
213 * dumps an optimization hash into human readable form
215 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
217 if (pset_count(set) > 0) {
219 const char *name = get_opt_name(index);
221 fprintf(dmp->f, "\n%s:\n", name);
222 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
224 foreach_pset(set, entry) {
225 fprintf(dmp->f, "%-16s %8u\n",
226 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
229 } /* simple_dump_opt_hash */
232 * dumps the register pressure for each block and for each register class
234 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
236 be_block_entry_t *b_entry = pset_first(entry->be_block_hash);
237 reg_pressure_entry_t *rp_entry;
239 /* return if no be statistic information available */
243 fprintf(dmp->f, "\nREG PRESSURE:\n");
244 fprintf(dmp->f, "%12s", "Block Nr");
246 /* print table head (register class names) */
247 foreach_pset(b_entry->reg_pressure, rp_entry)
248 fprintf(dmp->f, "%15s", rp_entry->class_name);
249 fprintf(dmp->f, "\n");
251 /* print the reg pressure for all blocks and register classes */
252 for (/* b_entry is already initialized */ ;
254 b_entry = pset_next(entry->be_block_hash)) {
255 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
257 foreach_pset(b_entry->reg_pressure, rp_entry)
258 fprintf(dmp->f, "%15d", rp_entry->pressure);
259 fprintf(dmp->f, "\n");
261 } /* simple_dump_be_block_reg_pressure */
263 /** prints a distribution entry */
264 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env) {
266 fprintf(dmp->f, "%12d", cnt_to_uint(&entry->cnt));
267 } /* simple_dump_distrib_entry */
270 * dumps the distribution of the amount of ready nodes for each block
272 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
274 if (pset_count(entry->be_block_hash) > 0) {
275 be_block_entry_t *b_entry;
278 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
279 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
280 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
282 foreach_pset(entry->be_block_hash, b_entry) {
283 /* this ensures that all keys from 1 to 5 are in the table */
284 for (i = 1; i < 6; ++i)
285 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
287 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
288 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
289 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
290 fprintf(dmp->f, "\n");
293 } /* simple_dump_be_block_sched_ready */
296 * Adds the counter for given entry to another distribution table.
298 static void add_distrib_entry(const distrib_entry_t *entry, void *env) {
299 distrib_tbl_t *sum_tbl = env;
301 stat_add_int_distrib_tbl(sum_tbl, PTR_TO_INT(entry->object), &entry->cnt);
302 } /* add_distrib_entry */
305 * dumps permutation statistics for one and block and one class
307 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
309 perm_stat_entry_t *ps_ent;
310 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
311 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
315 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
324 foreach_pset(entry->perm_stat, ps_ent) {
325 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
328 stat_get_count_distrib_tbl(ps_ent->chains),
329 stat_get_count_distrib_tbl(ps_ent->cycles),
334 /* sum up distribution table for chains */
335 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
337 /* sum up distribution table for cycles */
338 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
341 /* print chain distribution for all perms of this class in this block */
342 fprintf(dmp->f, "chain distribution:\n");
344 /* add all missing entries to chain distribution table */
345 for (i = 1; i <= entry->n_regs; i++) {
346 snprintf(buf, sizeof(buf), "length %d", i);
347 fprintf(dmp->f, "%12s", buf);
348 stat_insert_int_distrib_tbl(sum_chains, i);
350 fprintf(dmp->f, "\n");
351 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
352 fprintf(dmp->f, "\n");
354 /* print cycle distribution for all perms of this class in this block */
355 fprintf(dmp->f, "cycle distribution:\n");
357 /* add all missing entries to cycle distribution table */
358 for (i = 1; i <= entry->n_regs; i++) {
359 snprintf(buf, sizeof(buf), "length %d", i);
360 fprintf(dmp->f, "%12s", buf);
361 stat_insert_int_distrib_tbl(sum_cycles, i);
363 fprintf(dmp->f, "\n");
364 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
365 fprintf(dmp->f, "\n");
367 /* delete temporary sum distribution tables */
368 stat_delete_distrib_tbl(sum_chains);
369 stat_delete_distrib_tbl(sum_cycles);
371 } /* simple_dump_be_block_permstat_class */
374 * dumps statistics about perms
376 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
378 if (pset_count(entry->be_block_hash) > 0) {
379 be_block_entry_t *b_entry;
381 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
382 foreach_pset(entry->be_block_hash, b_entry) {
383 perm_class_entry_t *pc_ent;
385 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
387 if (b_entry->perm_class_stat) {
388 foreach_pset(b_entry->perm_class_stat, pc_ent) {
389 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
390 simple_dump_be_block_permstat_class(dmp, pc_ent);
395 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
397 } /* simple_dump_be_block_permstat */
400 * dumps the number of real_function_call optimization
402 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
407 if (! cnt_eq(cnt, 0)) {
408 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
409 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
411 } /* simple_dump_real_func_calls */
414 * dumps the number of tail_recursion optimization
416 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
421 if (num_tail_recursion > 0) {
422 fprintf(dmp->f, "\nTail recursion optimized:\n");
423 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
425 } /* simple_dump_tail_recursion */
428 * dumps the edges count
430 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
435 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
436 } /* simple_dump_edges */
441 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
443 int i, dump_opts = 1;
444 block_entry_t *b_entry;
445 extbb_entry_t *eb_entry;
451 ir_graph *const_irg = get_const_code_irg();
453 if (entry->irg == const_irg)
454 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
457 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
459 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
462 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
463 " was inlined : %u\n"
464 " got inlined : %u\n"
465 " strength red : %u\n"
466 " leaf function : %s\n"
467 " calls only leaf functions : %s\n"
471 " indirect calls : %u\n",
472 entry->is_deleted ? "DELETED " : "",
473 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
474 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
475 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
476 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
477 entry->is_leaf ? "YES" : "NO",
478 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
479 entry->is_recursive ? "YES" : "NO",
480 entry->is_chain_call ? "YES" : "NO",
481 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
482 cnt_to_uint(&entry->cnt[gcnt_indirect_calls])
485 for (i = 0; i < IF_RESULT_LAST; ++i) {
486 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
489 fprintf(dmp->f, "\nGlobals counts:\n");
490 fprintf(dmp->f, "--------------\n");
496 " pure address calc ops : %u\n"
497 " all address calc ops : %u\n",
498 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
499 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
502 /* Load/Store address classification */
504 " global Ld/St address : %u\n"
505 " local Ld/St address : %u\n"
506 " this Ld/St address : %u\n"
507 " param Ld/St address : %u\n"
508 " other Ld/St address : %u\n",
509 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
510 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
511 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
512 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
513 cnt_to_uint(&entry->cnt[gcnt_other_adr])
516 simple_dump_opcode_hash(dmp, entry->opcode_hash);
517 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
519 /* effects of optimizations */
523 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
524 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
526 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
527 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
530 /* dump block info */
531 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
532 foreach_pset(entry->block_hash, b_entry) {
533 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f\n",
535 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
536 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
537 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
538 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
539 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
540 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes])
544 /* dump block reg pressure */
545 simple_dump_be_block_reg_pressure(dmp, entry);
547 /* dump block ready nodes distribution */
548 simple_dump_be_block_sched_ready(dmp, entry);
550 /* dump block permutation statistics */
551 simple_dump_be_block_permstat(dmp, entry);
553 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
554 /* dump extended block info */
555 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
556 foreach_pset(entry->extbb_hash, eb_entry) {
557 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
559 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
560 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
561 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
562 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
563 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
564 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
569 } /* simple_dump_graph */
572 * dumps the constant table
574 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
584 fprintf(dmp->f, "\nConstant Information:\n");
585 fprintf(dmp->f, "---------------------\n");
587 fprintf(dmp->f, "\nBit usage for integer constants\n");
588 fprintf(dmp->f, "-------------------------------\n");
590 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
591 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
592 cnt_add(&sum, &tbl->int_bits_count[i]);
594 fprintf(dmp->f, "-------------------------------\n");
596 fprintf(dmp->f, "\nFloating point constants classification\n");
597 fprintf(dmp->f, "--------------------------------------\n");
598 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
599 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
600 cnt_add(&sum, &tbl->floats[i]);
602 fprintf(dmp->f, "--------------------------------------\n");
604 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
605 cnt_add(&sum, &tbl->others);
606 fprintf(dmp->f, "-------------------------------\n");
608 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
609 } /* simple_dump_const_tbl */
612 * Dumps a line of the parameter table
614 static void dump_tbl_line(const distrib_entry_t *entry, void *env) {
617 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
618 } /* dump_tbl_line */
621 * dumps the parameter distribution table
623 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
624 fprintf(dmp->f, "\nCall parameter Information:\n");
625 fprintf(dmp->f, "---------------------\n");
627 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
628 fprintf(dmp->f, "-------------------------------\n");
630 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
631 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
632 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
633 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
634 } /* simple_dump_param_tbl */
637 * dumps the optimization counter table
639 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
642 fprintf(dmp->f, "\nOptimization counts:\n");
643 fprintf(dmp->f, "---------------------\n");
645 for (i = 0; i < len; ++i) {
646 unsigned cnt = cnt_to_uint(&tbl[i]);
649 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
652 } /* simple_dump_opt_cnt */
655 * initialize the simple dumper
657 static void simple_init(dumper_t *dmp, const char *name) {
660 snprintf(fname, sizeof(fname), "%s.txt", name);
661 dmp->f = fopen(fname, "w");
668 * finishes the simple dumper
670 static void simple_finish(dumper_t *dmp) {
674 } /* simple_finish */
677 * the simple human readable dumper
679 const dumper_t simple_dumper = {
681 simple_dump_const_tbl,
682 simple_dump_param_tbl,
690 FOURCC('S', 'M', 'P', 'L'),
693 /* ---------------------------------------------------------------------- */
696 * count the nodes as needed:
698 * 1 normal (data) Phi's
703 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
708 for (i = 0; i < 4; ++i)
711 foreach_pset(graph->opcode_hash, entry) {
712 if (entry->op == op_Phi) {
714 cnt_add(&cnt[1], &entry->cnt_alive);
715 } else if (entry->op == dmp->status->op_PhiM) {
717 cnt_add(&cnt[2], &entry->cnt_alive);
718 } else if (entry->op == op_Proj) {
720 cnt_add(&cnt[3], &entry->cnt_alive);
722 /* all other nodes */
723 cnt_add(&cnt[0], &entry->cnt_alive);
726 } /* csv_count_nodes */
731 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
739 if (entry->irg && !entry->is_deleted) {
740 ir_graph *const_irg = get_const_code_irg();
742 if (entry->irg == const_irg) {
743 name = "<Const code Irg>";
747 name = get_entity_name(entry->ent);
749 name = "<UNKNOWN IRG>";
752 csv_count_nodes(dmp, entry, cnt);
754 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
757 cnt_to_uint(&cnt[0]),
758 cnt_to_uint(&cnt[1]),
759 cnt_to_uint(&cnt[2]),
763 } /* csv_dump_graph */
768 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
773 } /* csv_dump_const_tbl */
776 * dumps the parameter distribution table
778 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
783 } /* csv_dump_param_tbl */
786 * dumps the optimization counter
788 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
793 } /* csv_dump_opt_cnt */
796 * initialize the simple dumper
798 static void csv_init(dumper_t *dmp, const char *name)
802 snprintf(fname, sizeof(fname), "%s.csv", name);
803 dmp->f = fopen(fname, "a");
809 * finishes the simple dumper
811 static void csv_finish(dumper_t *dmp)
819 * the simple human readable dumper
821 const dumper_t csv_dumper = {
832 FOURCC('C', 'S', 'V', '\0')