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,"boolean 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_BOOL, "boolean simplification: Muxb(sel, true, false) = sel" },
101 { FS_OPT_MUX_NOT_BOOL, "boolean simplification: Muxb(sel, false, true) = Not(sel)" },
102 { FS_OPT_MUX_OR_BOOL, "boolean simplification: Muxb(sel, true, x) = Or(sel, x)" },
103 { FS_OPT_MUX_ORNOT_BOOL, "boolean simplification: Muxb(sel, x, true) = Or(Not(sel), x)" },
104 { FS_OPT_MUX_AND_BOOL, "boolean simplification: Muxb(sel, x, false) = And(sel, x)" },
105 { FS_OPT_MUX_ANDNOT_BOOL,"boolean simplification: Muxb(sel, false, x) = And(Not(sel), x)" },
106 { FS_OPT_MUX_C, "algebraic simplification: Mux(C, f, t) = C ? t : f" },
107 { FS_OPT_MUX_EQ, "algebraic simplification: Mux(v, x, x) = x" },
108 { FS_OPT_MUX_TRANSFORM, "algebraic simplification: Mux(a, b, c) = b OR Mux(a,b, c) = c" },
109 { FS_OPT_MUX_TO_MIN, "algebraic simplification: Mux(a < b, a, b) = Min(a,b)" },
110 { FS_OPT_MUX_TO_MAX, "algebraic simplification: Mux(a > b, a, b) = Max(a,b)" },
111 { FS_OPT_MUX_TO_ABS, "algebraic simplification: Mux(a > b, a, b) = Abs(a,b)" },
112 { FS_OPT_MUX_TO_SHR, "algebraic simplification: Mux(a > b, a, b) = a >> b" },
113 { FS_OPT_IDEM_UNARY, "algebraic simplification: Idempotent unary operation" },
114 { FS_OPT_MINUS_NOT, "algebraic simplification: -(~x) = x + 1" },
115 { FS_OPT_NOT_MINUS_1, "algebraic simplification: ~(x - 1) = -x" },
116 { FS_OPT_NOT_PLUS_1, "algebraic simplification: ~x + 1 = -x" },
117 { FS_OPT_ADD_X_NOT_X, "algebraic simplification: ~x + x = -1" },
118 { FS_OPT_FP_INV_MUL, "algebraic simplification: x / y = x * (1.0/y)" },
119 { FS_OPT_ABS_MINUS_X, "algebraic simplification: Abs(-x) = Abs(x)" },
120 { FS_OPT_CONST_PHI, "constant evaluation on Phi node" },
121 { FS_OPT_PREDICATE, "predicate optimization" },
122 { FS_OPT_DEMORGAN, "optimization using DeMorgan's law" },
123 { FS_OPT_CMP_OP_OP, "CMP optimization: Cmp(OP(x), OP(y)) = Cmp(x, y)" },
124 { FS_OPT_CMP_OP_C, "CMP optimization: Cmp(OP(x), c1) = Cmp(x, c2)" },
125 { FS_OPT_CMP_CONV_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(x, y)" },
126 { FS_OPT_CMP_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(Conv(x), y)" },
127 { FS_OPT_CMP_TO_BOOL, "CMP optimization: Cmp(x, y) = BoolOP(x, y)" },
128 { FS_OPT_CMP_CNST_MAGN, "CMP optimization: reduced magnitude of a const" },
129 { FS_OPT_CMP_SHF_TO_AND, "CMP optimization: transformed shift into And" },
130 { FS_OPT_CMP_MOD_TO_AND, "CMP optimization: transformed Mod into And" },
131 { FS_OPT_RTS_ABS, "RTS optimization: call to abs() replaced" },
132 { FS_OPT_RTS_ALLOCA, "RTS optimization: call to alloca() replaced" },
133 { FS_OPT_RTS_SQRT, "RTS optimization: call to sqrt() replaced" },
134 { FS_OPT_RTS_CBRT, "RTS optimization: call to cbrt() replaced" },
135 { FS_OPT_RTS_POW, "RTS optimization: call to pow() replaced" },
136 { FS_OPT_RTS_EXP, "RTS optimization: call to exp() replaced" },
137 { FS_OPT_RTS_LOG, "RTS optimization: call to log() replaced" },
138 { FS_OPT_RTS_SIN, "RTS optimization: call to sin() replaced" },
139 { FS_OPT_RTS_COS, "RTS optimization: call to cos() replaced" },
140 { FS_OPT_RTS_TAN, "RTS optimization: call to tan() replaced" },
141 { FS_OPT_RTS_ASIN, "RTS optimization: call to asin() replaced" },
142 { FS_OPT_RTS_ACOS, "RTS optimization: call to atan() replaced" },
143 { FS_OPT_RTS_ATAN, "RTS optimization: call to acos() replaced" },
144 { FS_OPT_RTS_SINH, "RTS optimization: call to sinh() replaced" },
145 { FS_OPT_RTS_COSH, "RTS optimization: call to cosh() replaced" },
146 { FS_OPT_RTS_TANH, "RTS optimization: call to tanh() replaced" },
147 { FS_OPT_RTS_SYMMETRIC, "RTS optimization: call to symmetric function f(-x) replaced by f(x)" },
148 { FS_OPT_RTS_STRCMP, "RTS optimization: call to strcmp() replaced" },
149 { FS_OPT_RTS_STRNCMP, "RTS optimization: call to strncmp() replaced" },
150 { FS_OPT_RTS_MEMCPY, "RTS optimization: call to memcpy() replaced" },
151 { FS_OPT_RTS_MEMSET, "RTS optimization: call to memset() replaced" },
152 { FS_OPT_RTS_STRLEN, "RTS optimization: call to strlen() replaced" },
153 { FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
154 { FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
155 { FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
156 { FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
157 { FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
158 { FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
159 { FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
160 { FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
161 { FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
162 { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
163 { FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
166 static const char *if_conv_names[IF_RESULT_LAST] = {
168 "if conv side effect ",
169 "if conv Phi node found ",
170 "if conv to deep DAG's ",
171 "if conv bad control flow ",
172 "if conv denied by arch ",
176 * dumps a opcode hash into human readable form
178 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
182 counter_t f_new_node;
186 cnt_clr(&f_new_node);
189 fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
190 foreach_pset(set, entry) {
191 fprintf(dmp->f, "%-16s %8u %8u %8u\n",
192 get_id_str(entry->op->name),
193 cnt_to_uint(&entry->cnt_alive),
194 cnt_to_uint(&entry->new_node),
195 cnt_to_uint(&entry->into_Id)
198 cnt_add(&f_alive, &entry->cnt_alive);
199 cnt_add(&f_new_node, &entry->new_node);
200 cnt_add(&f_Id, &entry->into_Id);
202 fprintf(dmp->f, "-------------------------------------------\n");
203 fprintf(dmp->f, "%-16s %8u %8u %8u\n", "Sum",
204 cnt_to_uint(&f_alive),
205 cnt_to_uint(&f_new_node),
208 } /* simple_dump_opcode_hash */
211 * Return the name of an optimization.
213 static const char *get_opt_name(int index) {
214 assert(index < (int) ARR_SIZE(opt_names) && "index out of range");
215 assert((int) opt_names[index].kind == index && "opt_names broken");
216 return opt_names[index].name;
220 * dumps an optimization hash into human readable form
222 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
224 if (pset_count(set) > 0) {
226 const char *name = get_opt_name(index);
228 fprintf(dmp->f, "\n%s:\n", name);
229 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
231 foreach_pset(set, entry) {
232 fprintf(dmp->f, "%-16s %8u\n",
233 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
236 } /* simple_dump_opt_hash */
239 * dumps the register pressure for each block and for each register class
241 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
243 be_block_entry_t *b_entry = pset_first(entry->be_block_hash);
244 reg_pressure_entry_t *rp_entry;
246 /* return if no be statistic information available */
250 fprintf(dmp->f, "\nREG PRESSURE:\n");
251 fprintf(dmp->f, "%12s", "Block Nr");
253 /* print table head (register class names) */
254 foreach_pset(b_entry->reg_pressure, rp_entry)
255 fprintf(dmp->f, "%15s", rp_entry->class_name);
256 fprintf(dmp->f, "\n");
258 /* print the reg pressure for all blocks and register classes */
259 for (/* b_entry is already initialized */ ;
261 b_entry = pset_next(entry->be_block_hash)) {
262 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
264 foreach_pset(b_entry->reg_pressure, rp_entry)
265 fprintf(dmp->f, "%15d", rp_entry->pressure);
266 fprintf(dmp->f, "\n");
268 } /* simple_dump_be_block_reg_pressure */
270 /** prints a distribution entry */
271 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env) {
273 fprintf(dmp->f, "%12d", cnt_to_uint(&entry->cnt));
274 } /* simple_dump_distrib_entry */
277 * dumps the distribution of the amount of ready nodes for each block
279 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
281 if (pset_count(entry->be_block_hash) > 0) {
282 be_block_entry_t *b_entry;
285 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
286 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
287 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
289 foreach_pset(entry->be_block_hash, b_entry) {
290 /* this ensures that all keys from 1 to 5 are in the table */
291 for (i = 1; i < 6; ++i)
292 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
294 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
295 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
296 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
297 fprintf(dmp->f, "\n");
300 } /* simple_dump_be_block_sched_ready */
303 * Adds the counter for given entry to another distribution table.
305 static void add_distrib_entry(const distrib_entry_t *entry, void *env) {
306 distrib_tbl_t *sum_tbl = env;
308 stat_add_int_distrib_tbl(sum_tbl, PTR_TO_INT(entry->object), &entry->cnt);
309 } /* add_distrib_entry */
312 * dumps permutation statistics for one and block and one class
314 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
316 perm_stat_entry_t *ps_ent;
317 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
318 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
322 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
331 foreach_pset(entry->perm_stat, ps_ent) {
332 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
335 stat_get_count_distrib_tbl(ps_ent->chains),
336 stat_get_count_distrib_tbl(ps_ent->cycles),
341 /* sum up distribution table for chains */
342 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
344 /* sum up distribution table for cycles */
345 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
348 /* print chain distribution for all perms of this class in this block */
349 fprintf(dmp->f, "chain distribution:\n");
351 /* add all missing entries to chain distribution table */
352 for (i = 1; i <= entry->n_regs; i++) {
353 snprintf(buf, sizeof(buf), "length %d", i);
354 fprintf(dmp->f, "%12s", buf);
355 stat_insert_int_distrib_tbl(sum_chains, i);
357 fprintf(dmp->f, "\n");
358 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
359 fprintf(dmp->f, "\n");
361 /* print cycle distribution for all perms of this class in this block */
362 fprintf(dmp->f, "cycle distribution:\n");
364 /* add all missing entries to cycle distribution table */
365 for (i = 1; i <= entry->n_regs; i++) {
366 snprintf(buf, sizeof(buf), "length %d", i);
367 fprintf(dmp->f, "%12s", buf);
368 stat_insert_int_distrib_tbl(sum_cycles, i);
370 fprintf(dmp->f, "\n");
371 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
372 fprintf(dmp->f, "\n");
374 /* delete temporary sum distribution tables */
375 stat_delete_distrib_tbl(sum_chains);
376 stat_delete_distrib_tbl(sum_cycles);
378 } /* simple_dump_be_block_permstat_class */
381 * dumps statistics about perms
383 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
385 if (pset_count(entry->be_block_hash) > 0) {
386 be_block_entry_t *b_entry;
388 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
389 foreach_pset(entry->be_block_hash, b_entry) {
390 perm_class_entry_t *pc_ent;
392 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
394 if (b_entry->perm_class_stat) {
395 foreach_pset(b_entry->perm_class_stat, pc_ent) {
396 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
397 simple_dump_be_block_permstat_class(dmp, pc_ent);
402 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
404 } /* simple_dump_be_block_permstat */
407 * dumps the number of real_function_call optimization
409 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
414 if (! cnt_eq(cnt, 0)) {
415 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
416 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
418 } /* simple_dump_real_func_calls */
421 * dumps the number of tail_recursion optimization
423 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
428 if (num_tail_recursion > 0) {
429 fprintf(dmp->f, "\nTail recursion optimized:\n");
430 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
432 } /* simple_dump_tail_recursion */
435 * dumps the edges count
437 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
442 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
443 } /* simple_dump_edges */
448 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
450 int i, dump_opts = 1;
451 block_entry_t *b_entry;
452 extbb_entry_t *eb_entry;
458 ir_graph *const_irg = get_const_code_irg();
460 if (entry->irg == const_irg)
461 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
464 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
466 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
469 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
470 " was inlined : %u\n"
471 " got inlined : %u\n"
472 " strength red : %u\n"
473 " leaf function : %s\n"
474 " calls only leaf functions : %s\n"
478 " indirect calls : %u\n"
479 " external calls : %u\n",
480 entry->is_deleted ? "DELETED " : "",
481 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
482 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
483 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
484 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
485 entry->is_leaf ? "YES" : "NO",
486 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
487 entry->is_recursive ? "YES" : "NO",
488 entry->is_chain_call ? "YES" : "NO",
489 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
490 cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
491 cnt_to_uint(&entry->cnt[gcnt_external_calls])
494 for (i = 0; i < IF_RESULT_LAST; ++i) {
495 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
498 fprintf(dmp->f, "\nGlobals counts:\n");
499 fprintf(dmp->f, "--------------\n");
505 " pure address calc ops : %u\n"
506 " all address calc ops : %u\n",
507 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
508 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
511 /* Load/Store address classification */
513 " global Ld/St address : %u\n"
514 " local Ld/St address : %u\n"
515 " this Ld/St address : %u\n"
516 " param Ld/St address : %u\n"
517 " other Ld/St address : %u\n",
518 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
519 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
520 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
521 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
522 cnt_to_uint(&entry->cnt[gcnt_other_adr])
525 simple_dump_opcode_hash(dmp, entry->opcode_hash);
526 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
528 /* effects of optimizations */
532 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
533 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
535 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
536 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
539 /* dump block info */
540 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
541 foreach_pset(entry->block_hash, b_entry) {
542 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
544 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
545 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
546 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
547 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
548 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
549 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
550 b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
554 /* dump block reg pressure */
555 simple_dump_be_block_reg_pressure(dmp, entry);
557 /* dump block ready nodes distribution */
558 simple_dump_be_block_sched_ready(dmp, entry);
560 /* dump block permutation statistics */
561 simple_dump_be_block_permstat(dmp, entry);
563 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
564 /* dump extended block info */
565 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
566 foreach_pset(entry->extbb_hash, eb_entry) {
567 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
569 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
570 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
571 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
572 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
573 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
574 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
579 } /* simple_dump_graph */
582 * dumps the constant table
584 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
594 fprintf(dmp->f, "\nConstant Information:\n");
595 fprintf(dmp->f, "---------------------\n");
597 fprintf(dmp->f, "\nBit usage for integer constants\n");
598 fprintf(dmp->f, "-------------------------------\n");
600 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
601 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
602 cnt_add(&sum, &tbl->int_bits_count[i]);
604 fprintf(dmp->f, "-------------------------------\n");
606 fprintf(dmp->f, "\nFloating point constants classification\n");
607 fprintf(dmp->f, "--------------------------------------\n");
608 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
609 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
610 cnt_add(&sum, &tbl->floats[i]);
612 fprintf(dmp->f, "--------------------------------------\n");
614 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
615 cnt_add(&sum, &tbl->others);
616 fprintf(dmp->f, "-------------------------------\n");
618 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
619 } /* simple_dump_const_tbl */
622 * Dumps a line of the parameter table
624 static void dump_tbl_line(const distrib_entry_t *entry, void *env) {
627 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
628 } /* dump_tbl_line */
631 * dumps the parameter distribution table
633 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
634 fprintf(dmp->f, "\nCall parameter Information:\n");
635 fprintf(dmp->f, "---------------------\n");
637 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
638 fprintf(dmp->f, "-------------------------------\n");
640 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
641 fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
642 fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
643 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
644 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
645 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
646 } /* simple_dump_param_tbl */
649 * dumps the optimization counter table
651 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
654 fprintf(dmp->f, "\nOptimization counts:\n");
655 fprintf(dmp->f, "---------------------\n");
657 for (i = 0; i < len; ++i) {
658 unsigned cnt = cnt_to_uint(&tbl[i]);
661 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
664 } /* simple_dump_opt_cnt */
667 * initialize the simple dumper
669 static void simple_init(dumper_t *dmp, const char *name) {
672 snprintf(fname, sizeof(fname), "%s.txt", name);
673 dmp->f = fopen(fname, "w");
680 * finishes the simple dumper
682 static void simple_finish(dumper_t *dmp) {
686 } /* simple_finish */
689 * the simple human readable dumper
691 const dumper_t simple_dumper = {
693 simple_dump_const_tbl,
694 simple_dump_param_tbl,
702 FOURCC('S', 'M', 'P', 'L'),
705 /* ---------------------------------------------------------------------- */
708 * count the nodes as needed:
710 * 1 normal (data) Phi's
715 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
720 for (i = 0; i < 4; ++i)
723 foreach_pset(graph->opcode_hash, entry) {
724 if (entry->op == op_Phi) {
726 cnt_add(&cnt[1], &entry->cnt_alive);
727 } else if (entry->op == dmp->status->op_PhiM) {
729 cnt_add(&cnt[2], &entry->cnt_alive);
730 } else if (entry->op == op_Proj) {
732 cnt_add(&cnt[3], &entry->cnt_alive);
734 /* all other nodes */
735 cnt_add(&cnt[0], &entry->cnt_alive);
738 } /* csv_count_nodes */
743 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
751 if (entry->irg && !entry->is_deleted) {
752 ir_graph *const_irg = get_const_code_irg();
754 if (entry->irg == const_irg) {
755 name = "<Const code Irg>";
759 name = get_entity_name(entry->ent);
761 name = "<UNKNOWN IRG>";
764 csv_count_nodes(dmp, entry, cnt);
766 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
769 cnt_to_uint(&cnt[0]),
770 cnt_to_uint(&cnt[1]),
771 cnt_to_uint(&cnt[2]),
775 } /* csv_dump_graph */
780 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
785 } /* csv_dump_const_tbl */
788 * dumps the parameter distribution table
790 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
795 } /* csv_dump_param_tbl */
798 * dumps the optimization counter
800 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
805 } /* csv_dump_opt_cnt */
808 * initialize the simple dumper
810 static void csv_init(dumper_t *dmp, const char *name)
814 snprintf(fname, sizeof(fname), "%s.csv", name);
815 dmp->f = fopen(fname, "a");
821 * finishes the simple dumper
823 static void csv_finish(dumper_t *dmp)
831 * the simple human readable dumper
833 const dumper_t csv_dumper = {
844 FOURCC('C', 'S', 'V', '\0')