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_SUB_TO_NOT, "algebraic simplification: -1 - x -> ~x" },
82 { FS_OPT_SUB_TO_CONV, "algebraic simplification: a - NULL = (int)a" },
83 { FS_OPT_MUL_MINUS, "algebraic simplification: (-a) * (b - c) = a * (c - b)" },
84 { FS_OPT_MUL_MINUS_1, "algebraic simplification: a * -1 = -a" },
85 { FS_OPT_MINUS_MUL_C, "algebraic simplification: (-a) * C = a * (-C)" },
86 { FS_OPT_MUL_MINUS_MINUS,"algebraic simplification: (-a) * (-b) = a * b" },
87 { FS_OPT_OR, "algebraic simplification: a | a = a | 0 = 0 | a = a" },
88 { FS_OPT_AND, "algebraic simplification: a & 0b1...1 = 0b1...1 & a = a & a = (a|X) & a = a" },
89 { FS_OPT_TO_EOR, "algebraic simplification: (a|b) & ~(a&b) = a^b" },
90 { FS_OPT_EOR_A_A, "algebraic simplification: a ^ a = 0" },
91 { FS_OPT_EOR_A_B_A, "algebraic simplification: (a ^ b) ^ a = b" },
92 { FS_OPT_EOR_TO_NOT_BOOL,"boolean simplification: bool ^ 1 = !bool" },
93 { FS_OPT_EOR_TO_NOT, "algebraic simplification: x ^ 0b1..1 = ~x, (a ^ b) & b = ~a & b" },
94 { FS_OPT_NOT_CMP, "algebraic simplification: !(a cmp b) = a !cmp b" },
95 { FS_OPT_OR_SHFT_TO_ROTL,"algebraic simplification: (x << c) | (x >> (bits - c)) == Rotl(x, c)" },
96 { FS_OPT_REASSOC_SHIFT, "algebraic simplification: (x SHF c1) SHF c2 = x SHF (c1+c2)" },
97 { FS_OPT_SHIFT_AND, "algebraic simplification: (a SHF c) AND (b SHF c) = (a AND b) SHF c" },
98 { FS_OPT_SHIFT_OR, "algebraic simplification: (a SHF c) OR (b SHF c) = (a OR b) SHF c" },
99 { FS_OPT_SHIFT_EOR, "algebraic simplification: (a SHF c) XOR (b SHF c) = (a XOR b) SHF c" },
100 { FS_OPT_CONV, "algebraic simplification: Conv could be removed" },
101 { FS_OPT_CAST, "algebraic simplification: a Cast could be removed" },
102 { FS_OPT_MIN_MAX_EQ, "algebraic simplification: Min(a,a) = Max(a,a) = a" },
103 { FS_OPT_MUX_BOOL, "boolean simplification: Muxb(sel, true, false) = sel" },
104 { FS_OPT_MUX_NOT_BOOL, "boolean simplification: Muxb(sel, false, true) = Not(sel)" },
105 { FS_OPT_MUX_OR_BOOL, "boolean simplification: Muxb(sel, true, x) = Or(sel, x)" },
106 { FS_OPT_MUX_ORNOT_BOOL, "boolean simplification: Muxb(sel, x, true) = Or(Not(sel), x)" },
107 { FS_OPT_MUX_AND_BOOL, "boolean simplification: Muxb(sel, x, false) = And(sel, x)" },
108 { FS_OPT_MUX_ANDNOT_BOOL,"boolean simplification: Muxb(sel, false, x) = And(Not(sel), x)" },
109 { FS_OPT_MUX_C, "algebraic simplification: Mux(C, f, t) = C ? t : f" },
110 { FS_OPT_MUX_EQ, "algebraic simplification: Mux(v, x, x) = x" },
111 { FS_OPT_MUX_TRANSFORM, "algebraic simplification: Mux(a, b, c) = b OR Mux(a,b, c) = c" },
112 { FS_OPT_MUX_TO_MIN, "algebraic simplification: Mux(a < b, a, b) = Min(a,b)" },
113 { FS_OPT_MUX_TO_MAX, "algebraic simplification: Mux(a > b, a, b) = Max(a,b)" },
114 { FS_OPT_MUX_TO_ABS, "algebraic simplification: Mux(a > b, a, b) = Abs(a,b)" },
115 { FS_OPT_MUX_TO_SHR, "algebraic simplification: Mux(a > b, a, b) = a >> b" },
116 { FS_OPT_IDEM_UNARY, "algebraic simplification: Idempotent unary operation" },
117 { FS_OPT_MINUS_NOT, "algebraic simplification: -(~x) = x + 1" },
118 { FS_OPT_NOT_MINUS_1, "algebraic simplification: ~(x - 1) = -x" },
119 { FS_OPT_NOT_PLUS_1, "algebraic simplification: ~x + 1 = -x" },
120 { FS_OPT_ADD_X_NOT_X, "algebraic simplification: ~x + x = -1" },
121 { FS_OPT_FP_INV_MUL, "algebraic simplification: x / y = x * (1.0/y)" },
122 { FS_OPT_ABS_MINUS_X, "algebraic simplification: Abs(-x) = Abs(x)" },
123 { FS_OPT_CONST_PHI, "constant evaluation on Phi node" },
124 { FS_OPT_PREDICATE, "predicate optimization" },
125 { FS_OPT_DEMORGAN, "optimization using DeMorgan's law" },
126 { FS_OPT_CMP_OP_OP, "CMP optimization: Cmp(OP(x), OP(y)) = Cmp(x, y)" },
127 { FS_OPT_CMP_OP_C, "CMP optimization: Cmp(OP(x), c1) = Cmp(x, c2)" },
128 { FS_OPT_CMP_CONV_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(x, y)" },
129 { FS_OPT_CMP_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(Conv(x), y)" },
130 { FS_OPT_CMP_TO_BOOL, "CMP optimization: Cmp(x, y) = BoolOP(x, y)" },
131 { FS_OPT_CMP_CNST_MAGN, "CMP optimization: reduced magnitude of a const" },
132 { FS_OPT_CMP_SHF_TO_AND, "CMP optimization: transformed shift into And" },
133 { FS_OPT_CMP_MOD_TO_AND, "CMP optimization: transformed Mod into And" },
134 { FS_OPT_NOP, "the operation is a NOP" },
135 { FS_OPT_RTS_ABS, "RTS optimization: call to abs() replaced" },
136 { FS_OPT_RTS_ALLOCA, "RTS optimization: call to alloca() replaced" },
137 { FS_OPT_RTS_SQRT, "RTS optimization: call to sqrt() replaced" },
138 { FS_OPT_RTS_CBRT, "RTS optimization: call to cbrt() replaced" },
139 { FS_OPT_RTS_POW, "RTS optimization: call to pow() replaced" },
140 { FS_OPT_RTS_EXP, "RTS optimization: call to exp() replaced" },
141 { FS_OPT_RTS_LOG, "RTS optimization: call to log() replaced" },
142 { FS_OPT_RTS_SIN, "RTS optimization: call to sin() replaced" },
143 { FS_OPT_RTS_COS, "RTS optimization: call to cos() replaced" },
144 { FS_OPT_RTS_TAN, "RTS optimization: call to tan() replaced" },
145 { FS_OPT_RTS_ASIN, "RTS optimization: call to asin() replaced" },
146 { FS_OPT_RTS_ACOS, "RTS optimization: call to atan() replaced" },
147 { FS_OPT_RTS_ATAN, "RTS optimization: call to acos() replaced" },
148 { FS_OPT_RTS_SINH, "RTS optimization: call to sinh() replaced" },
149 { FS_OPT_RTS_COSH, "RTS optimization: call to cosh() replaced" },
150 { FS_OPT_RTS_TANH, "RTS optimization: call to tanh() replaced" },
151 { FS_OPT_RTS_SYMMETRIC, "RTS optimization: call to symmetric function f(-x) replaced by f(x)" },
152 { FS_OPT_RTS_STRCMP, "RTS optimization: call to strcmp() replaced" },
153 { FS_OPT_RTS_STRNCMP, "RTS optimization: call to strncmp() replaced" },
154 { FS_OPT_RTS_MEMCPY, "RTS optimization: call to memcpy() replaced" },
155 { FS_OPT_RTS_MEMSET, "RTS optimization: call to memset() replaced" },
156 { FS_OPT_RTS_STRLEN, "RTS optimization: call to strlen() replaced" },
157 { FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
158 { FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
159 { FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
160 { FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
161 { FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
162 { FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
163 { FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
164 { FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
165 { FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
166 { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
167 { FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
170 static const char *if_conv_names[IF_RESULT_LAST] = {
172 "if conv side effect ",
173 "if conv Phi node found ",
174 "if conv to deep DAG's ",
175 "if conv bad control flow ",
176 "if conv denied by arch ",
180 * dumps a opcode hash into human readable form
182 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
186 counter_t f_new_node;
190 cnt_clr(&f_new_node);
193 fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
194 foreach_pset(set, entry) {
195 fprintf(dmp->f, "%-16s %8u %8u %8u\n",
196 get_id_str(entry->op->name),
197 cnt_to_uint(&entry->cnt_alive),
198 cnt_to_uint(&entry->new_node),
199 cnt_to_uint(&entry->into_Id)
202 cnt_add(&f_alive, &entry->cnt_alive);
203 cnt_add(&f_new_node, &entry->new_node);
204 cnt_add(&f_Id, &entry->into_Id);
206 fprintf(dmp->f, "-------------------------------------------\n");
207 fprintf(dmp->f, "%-16s %8u %8u %8u\n", "Sum",
208 cnt_to_uint(&f_alive),
209 cnt_to_uint(&f_new_node),
212 } /* simple_dump_opcode_hash */
215 * Return the name of an optimization.
217 static const char *get_opt_name(int index) {
218 assert(index < (int) ARR_SIZE(opt_names) && "index out of range");
219 assert((int) opt_names[index].kind == index && "opt_names broken");
220 return opt_names[index].name;
224 * dumps an optimization hash into human readable form
226 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
228 if (pset_count(set) > 0) {
230 const char *name = get_opt_name(index);
232 fprintf(dmp->f, "\n%s:\n", name);
233 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
235 foreach_pset(set, entry) {
236 fprintf(dmp->f, "%-16s %8u\n",
237 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
240 } /* simple_dump_opt_hash */
243 * dumps the register pressure for each block and for each register class
245 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
247 be_block_entry_t *b_entry = pset_first(entry->be_block_hash);
248 reg_pressure_entry_t *rp_entry;
250 /* return if no be statistic information available */
254 fprintf(dmp->f, "\nREG PRESSURE:\n");
255 fprintf(dmp->f, "%12s", "Block Nr");
257 /* print table head (register class names) */
258 foreach_pset(b_entry->reg_pressure, rp_entry)
259 fprintf(dmp->f, "%15s", rp_entry->class_name);
260 fprintf(dmp->f, "\n");
262 /* print the reg pressure for all blocks and register classes */
263 for (/* b_entry is already initialized */ ;
265 b_entry = pset_next(entry->be_block_hash)) {
266 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
268 foreach_pset(b_entry->reg_pressure, rp_entry)
269 fprintf(dmp->f, "%15d", rp_entry->pressure);
270 fprintf(dmp->f, "\n");
272 } /* simple_dump_be_block_reg_pressure */
274 /** prints a distribution entry */
275 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env) {
277 fprintf(dmp->f, "%12d", cnt_to_uint(&entry->cnt));
278 } /* simple_dump_distrib_entry */
281 * dumps the distribution of the amount of ready nodes for each block
283 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
285 if (pset_count(entry->be_block_hash) > 0) {
286 be_block_entry_t *b_entry;
289 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
290 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
291 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
293 foreach_pset(entry->be_block_hash, b_entry) {
294 /* this ensures that all keys from 1 to 5 are in the table */
295 for (i = 1; i < 6; ++i)
296 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
298 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
299 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
300 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
301 fprintf(dmp->f, "\n");
304 } /* simple_dump_be_block_sched_ready */
307 * Adds the counter for given entry to another distribution table.
309 static void add_distrib_entry(const distrib_entry_t *entry, void *env) {
310 distrib_tbl_t *sum_tbl = env;
312 stat_add_int_distrib_tbl(sum_tbl, PTR_TO_INT(entry->object), &entry->cnt);
313 } /* add_distrib_entry */
316 * dumps permutation statistics for one and block and one class
318 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
320 perm_stat_entry_t *ps_ent;
321 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
322 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
326 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
335 foreach_pset(entry->perm_stat, ps_ent) {
336 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
339 stat_get_count_distrib_tbl(ps_ent->chains),
340 stat_get_count_distrib_tbl(ps_ent->cycles),
345 /* sum up distribution table for chains */
346 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
348 /* sum up distribution table for cycles */
349 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
352 /* print chain distribution for all perms of this class in this block */
353 fprintf(dmp->f, "chain distribution:\n");
355 /* add all missing entries to chain distribution table */
356 for (i = 1; i <= entry->n_regs; i++) {
357 snprintf(buf, sizeof(buf), "length %d", i);
358 fprintf(dmp->f, "%12s", buf);
359 stat_insert_int_distrib_tbl(sum_chains, i);
361 fprintf(dmp->f, "\n");
362 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
363 fprintf(dmp->f, "\n");
365 /* print cycle distribution for all perms of this class in this block */
366 fprintf(dmp->f, "cycle distribution:\n");
368 /* add all missing entries to cycle distribution table */
369 for (i = 1; i <= entry->n_regs; i++) {
370 snprintf(buf, sizeof(buf), "length %d", i);
371 fprintf(dmp->f, "%12s", buf);
372 stat_insert_int_distrib_tbl(sum_cycles, i);
374 fprintf(dmp->f, "\n");
375 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
376 fprintf(dmp->f, "\n");
378 /* delete temporary sum distribution tables */
379 stat_delete_distrib_tbl(sum_chains);
380 stat_delete_distrib_tbl(sum_cycles);
382 } /* simple_dump_be_block_permstat_class */
385 * dumps statistics about perms
387 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
389 if (pset_count(entry->be_block_hash) > 0) {
390 be_block_entry_t *b_entry;
392 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
393 foreach_pset(entry->be_block_hash, b_entry) {
394 perm_class_entry_t *pc_ent;
396 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
398 if (b_entry->perm_class_stat) {
399 foreach_pset(b_entry->perm_class_stat, pc_ent) {
400 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
401 simple_dump_be_block_permstat_class(dmp, pc_ent);
406 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
408 } /* simple_dump_be_block_permstat */
411 * dumps the number of real_function_call optimization
413 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
418 if (! cnt_eq(cnt, 0)) {
419 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
420 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
422 } /* simple_dump_real_func_calls */
425 * dumps the number of tail_recursion optimization
427 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
432 if (num_tail_recursion > 0) {
433 fprintf(dmp->f, "\nTail recursion optimized:\n");
434 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
436 } /* simple_dump_tail_recursion */
439 * dumps the edges count
441 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
446 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
447 } /* simple_dump_edges */
452 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
454 int i, dump_opts = 1;
455 block_entry_t *b_entry;
456 extbb_entry_t *eb_entry;
462 ir_graph *const_irg = get_const_code_irg();
464 if (entry->irg == const_irg)
465 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
468 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
470 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
473 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
474 " was inlined : %u\n"
475 " got inlined : %u\n"
476 " strength red : %u\n"
477 " leaf function : %s\n"
478 " calls only leaf functions : %s\n"
482 " indirect calls : %u\n"
483 " external calls : %u\n",
484 entry->is_deleted ? "DELETED " : "",
485 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
486 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
487 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
488 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
489 entry->is_leaf ? "YES" : "NO",
490 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
491 entry->is_recursive ? "YES" : "NO",
492 entry->is_chain_call ? "YES" : "NO",
493 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
494 cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
495 cnt_to_uint(&entry->cnt[gcnt_external_calls])
498 for (i = 0; i < IF_RESULT_LAST; ++i) {
499 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
502 fprintf(dmp->f, "\nGlobals counts:\n");
503 fprintf(dmp->f, "--------------\n");
509 " pure address calc ops : %u\n"
510 " all address calc ops : %u\n",
511 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
512 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
515 /* Load/Store address classification */
517 " global Ld/St address : %u\n"
518 " local Ld/St address : %u\n"
519 " this Ld/St address : %u\n"
520 " param Ld/St address : %u\n"
521 " other Ld/St address : %u\n",
522 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
523 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
524 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
525 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
526 cnt_to_uint(&entry->cnt[gcnt_other_adr])
529 simple_dump_opcode_hash(dmp, entry->opcode_hash);
530 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
532 /* effects of optimizations */
536 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
537 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
539 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
540 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
543 /* dump block info */
544 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
545 foreach_pset(entry->block_hash, b_entry) {
546 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
548 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
549 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
550 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
551 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
552 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
553 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
554 b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
558 /* dump block reg pressure */
559 simple_dump_be_block_reg_pressure(dmp, entry);
561 /* dump block ready nodes distribution */
562 simple_dump_be_block_sched_ready(dmp, entry);
564 /* dump block permutation statistics */
565 simple_dump_be_block_permstat(dmp, entry);
567 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
568 /* dump extended block info */
569 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
570 foreach_pset(entry->extbb_hash, eb_entry) {
571 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
573 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
574 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
575 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
576 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
577 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
578 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
583 } /* simple_dump_graph */
586 * dumps the constant table
588 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
598 fprintf(dmp->f, "\nConstant Information:\n");
599 fprintf(dmp->f, "---------------------\n");
601 fprintf(dmp->f, "\nBit usage for integer constants\n");
602 fprintf(dmp->f, "-------------------------------\n");
604 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
605 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
606 cnt_add(&sum, &tbl->int_bits_count[i]);
608 fprintf(dmp->f, "-------------------------------\n");
610 fprintf(dmp->f, "\nFloating point constants classification\n");
611 fprintf(dmp->f, "--------------------------------------\n");
612 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
613 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
614 cnt_add(&sum, &tbl->floats[i]);
616 fprintf(dmp->f, "--------------------------------------\n");
618 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
619 cnt_add(&sum, &tbl->others);
620 fprintf(dmp->f, "-------------------------------\n");
622 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
623 } /* simple_dump_const_tbl */
626 * Dumps a line of the parameter table
628 static void dump_tbl_line(const distrib_entry_t *entry, void *env) {
631 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
632 } /* dump_tbl_line */
635 * dumps the parameter distribution table
637 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
638 fprintf(dmp->f, "\nCall parameter Information:\n");
639 fprintf(dmp->f, "---------------------\n");
641 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
642 fprintf(dmp->f, "-------------------------------\n");
644 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
645 fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
646 fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
647 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
648 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
649 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
650 } /* simple_dump_param_tbl */
653 * dumps the optimization counter table
655 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
658 fprintf(dmp->f, "\nOptimization counts:\n");
659 fprintf(dmp->f, "---------------------\n");
661 for (i = 0; i < len; ++i) {
662 unsigned cnt = cnt_to_uint(&tbl[i]);
665 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
668 } /* simple_dump_opt_cnt */
671 * initialize the simple dumper
673 static void simple_init(dumper_t *dmp, const char *name) {
676 snprintf(fname, sizeof(fname), "%s.txt", name);
677 dmp->f = fopen(fname, "w");
684 * finishes the simple dumper
686 static void simple_finish(dumper_t *dmp) {
690 } /* simple_finish */
693 * the simple human readable dumper
695 const dumper_t simple_dumper = {
697 simple_dump_const_tbl,
698 simple_dump_param_tbl,
706 FOURCC('S', 'M', 'P', 'L'),
709 /* ---------------------------------------------------------------------- */
712 * count the nodes as needed:
714 * 1 normal (data) Phi's
719 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
724 for (i = 0; i < 4; ++i)
727 foreach_pset(graph->opcode_hash, entry) {
728 if (entry->op == op_Phi) {
730 cnt_add(&cnt[1], &entry->cnt_alive);
731 } else if (entry->op == dmp->status->op_PhiM) {
733 cnt_add(&cnt[2], &entry->cnt_alive);
734 } else if (entry->op == op_Proj) {
736 cnt_add(&cnt[3], &entry->cnt_alive);
738 /* all other nodes */
739 cnt_add(&cnt[0], &entry->cnt_alive);
742 } /* csv_count_nodes */
747 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
755 if (entry->irg && !entry->is_deleted) {
756 ir_graph *const_irg = get_const_code_irg();
758 if (entry->irg == const_irg) {
759 name = "<Const code Irg>";
763 name = get_entity_name(entry->ent);
765 name = "<UNKNOWN IRG>";
768 csv_count_nodes(dmp, entry, cnt);
770 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
773 cnt_to_uint(&cnt[0]),
774 cnt_to_uint(&cnt[1]),
775 cnt_to_uint(&cnt[2]),
779 } /* csv_dump_graph */
784 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
789 } /* csv_dump_const_tbl */
792 * dumps the parameter distribution table
794 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
799 } /* csv_dump_param_tbl */
802 * dumps the optimization counter
804 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
809 } /* csv_dump_opt_cnt */
812 * initialize the simple dumper
814 static void csv_init(dumper_t *dmp, const char *name)
818 snprintf(fname, sizeof(fname), "%s.csv", name);
819 dmp->f = fopen(fname, "a");
825 * finishes the simple dumper
827 static void csv_finish(dumper_t *dmp)
835 * the simple human readable dumper
837 const dumper_t csv_dumper = {
848 FOURCC('C', 'S', 'V', '\0')