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_A_B_A, "algebraic simplification: (a ^ b) ^ a = b" },
90 { FS_OPT_EOR_TO_NOT_BOOL,"boolean simplification: bool ^ 1 = !bool" },
91 { FS_OPT_EOR_TO_NOT, "algebraic simplification: x ^ 0b1..1 = ~x, (a ^ b) & b = ~a & b" },
92 { FS_OPT_NOT_CMP, "algebraic simplification: !(a cmp b) = a !cmp b" },
93 { FS_OPT_OR_SHFT_TO_ROTL,"algebraic simplification: (x << c) | (x >> (bits - c)) == Rotl(x, c)" },
94 { FS_OPT_REASSOC_SHIFT, "algebraic simplification: (x SHF c1) SHF c2 = x SHF (c1+c2)" },
95 { FS_OPT_SHIFT_AND, "algebraic simplification: (a SHF c) AND (b SHF c) = (a AND b) SHF c" },
96 { FS_OPT_SHIFT_OR, "algebraic simplification: (a SHF c) OR (b SHF c) = (a OR b) SHF c" },
97 { FS_OPT_SHIFT_EOR, "algebraic simplification: (a SHF c) XOR (b SHF c) = (a XOR b) SHF c" },
98 { FS_OPT_CONV, "algebraic simplification: Conv could be removed" },
99 { FS_OPT_CAST, "algebraic simplification: a Cast could be removed" },
100 { FS_OPT_MIN_MAX_EQ, "algebraic simplification: Min(a,a) = Max(a,a) = a" },
101 { FS_OPT_MUX_BOOL, "boolean simplification: Muxb(sel, true, false) = sel" },
102 { FS_OPT_MUX_NOT_BOOL, "boolean simplification: Muxb(sel, false, true) = Not(sel)" },
103 { FS_OPT_MUX_OR_BOOL, "boolean simplification: Muxb(sel, true, x) = Or(sel, x)" },
104 { FS_OPT_MUX_ORNOT_BOOL, "boolean simplification: Muxb(sel, x, true) = Or(Not(sel), x)" },
105 { FS_OPT_MUX_AND_BOOL, "boolean simplification: Muxb(sel, x, false) = And(sel, x)" },
106 { FS_OPT_MUX_ANDNOT_BOOL,"boolean simplification: Muxb(sel, false, x) = And(Not(sel), x)" },
107 { FS_OPT_MUX_C, "algebraic simplification: Mux(C, f, t) = C ? t : f" },
108 { FS_OPT_MUX_EQ, "algebraic simplification: Mux(v, x, x) = x" },
109 { FS_OPT_MUX_TRANSFORM, "algebraic simplification: Mux(a, b, c) = b OR Mux(a,b, c) = c" },
110 { FS_OPT_MUX_TO_MIN, "algebraic simplification: Mux(a < b, a, b) = Min(a,b)" },
111 { FS_OPT_MUX_TO_MAX, "algebraic simplification: Mux(a > b, a, b) = Max(a,b)" },
112 { FS_OPT_MUX_TO_ABS, "algebraic simplification: Mux(a > b, a, b) = Abs(a,b)" },
113 { FS_OPT_MUX_TO_SHR, "algebraic simplification: Mux(a > b, a, b) = a >> b" },
114 { FS_OPT_IDEM_UNARY, "algebraic simplification: Idempotent unary operation" },
115 { FS_OPT_MINUS_NOT, "algebraic simplification: -(~x) = x + 1" },
116 { FS_OPT_NOT_MINUS_1, "algebraic simplification: ~(x - 1) = -x" },
117 { FS_OPT_NOT_PLUS_1, "algebraic simplification: ~x + 1 = -x" },
118 { FS_OPT_ADD_X_NOT_X, "algebraic simplification: ~x + x = -1" },
119 { FS_OPT_FP_INV_MUL, "algebraic simplification: x / y = x * (1.0/y)" },
120 { FS_OPT_ABS_MINUS_X, "algebraic simplification: Abs(-x) = Abs(x)" },
121 { FS_OPT_CONST_PHI, "constant evaluation on Phi node" },
122 { FS_OPT_PREDICATE, "predicate optimization" },
123 { FS_OPT_DEMORGAN, "optimization using DeMorgan's law" },
124 { FS_OPT_CMP_OP_OP, "CMP optimization: Cmp(OP(x), OP(y)) = Cmp(x, y)" },
125 { FS_OPT_CMP_OP_C, "CMP optimization: Cmp(OP(x), c1) = Cmp(x, c2)" },
126 { FS_OPT_CMP_CONV_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(x, y)" },
127 { FS_OPT_CMP_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(Conv(x), y)" },
128 { FS_OPT_CMP_TO_BOOL, "CMP optimization: Cmp(x, y) = BoolOP(x, y)" },
129 { FS_OPT_CMP_CNST_MAGN, "CMP optimization: reduced magnitude of a const" },
130 { FS_OPT_CMP_SHF_TO_AND, "CMP optimization: transformed shift into And" },
131 { FS_OPT_CMP_MOD_TO_AND, "CMP optimization: transformed Mod into And" },
132 { FS_OPT_RTS_ABS, "RTS optimization: call to abs() replaced" },
133 { FS_OPT_RTS_ALLOCA, "RTS optimization: call to alloca() replaced" },
134 { FS_OPT_RTS_SQRT, "RTS optimization: call to sqrt() replaced" },
135 { FS_OPT_RTS_CBRT, "RTS optimization: call to cbrt() replaced" },
136 { FS_OPT_RTS_POW, "RTS optimization: call to pow() replaced" },
137 { FS_OPT_RTS_EXP, "RTS optimization: call to exp() replaced" },
138 { FS_OPT_RTS_LOG, "RTS optimization: call to log() replaced" },
139 { FS_OPT_RTS_SIN, "RTS optimization: call to sin() replaced" },
140 { FS_OPT_RTS_COS, "RTS optimization: call to cos() replaced" },
141 { FS_OPT_RTS_TAN, "RTS optimization: call to tan() replaced" },
142 { FS_OPT_RTS_ASIN, "RTS optimization: call to asin() replaced" },
143 { FS_OPT_RTS_ACOS, "RTS optimization: call to atan() replaced" },
144 { FS_OPT_RTS_ATAN, "RTS optimization: call to acos() replaced" },
145 { FS_OPT_RTS_SINH, "RTS optimization: call to sinh() replaced" },
146 { FS_OPT_RTS_COSH, "RTS optimization: call to cosh() replaced" },
147 { FS_OPT_RTS_TANH, "RTS optimization: call to tanh() replaced" },
148 { FS_OPT_RTS_SYMMETRIC, "RTS optimization: call to symmetric function f(-x) replaced by f(x)" },
149 { FS_OPT_RTS_STRCMP, "RTS optimization: call to strcmp() replaced" },
150 { FS_OPT_RTS_STRNCMP, "RTS optimization: call to strncmp() replaced" },
151 { FS_OPT_RTS_MEMCPY, "RTS optimization: call to memcpy() replaced" },
152 { FS_OPT_RTS_MEMSET, "RTS optimization: call to memset() replaced" },
153 { FS_OPT_RTS_STRLEN, "RTS optimization: call to strlen() replaced" },
154 { FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
155 { FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
156 { FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
157 { FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
158 { FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
159 { FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
160 { FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
161 { FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
162 { FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
163 { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
164 { FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
167 static const char *if_conv_names[IF_RESULT_LAST] = {
169 "if conv side effect ",
170 "if conv Phi node found ",
171 "if conv to deep DAG's ",
172 "if conv bad control flow ",
173 "if conv denied by arch ",
177 * dumps a opcode hash into human readable form
179 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
183 counter_t f_new_node;
187 cnt_clr(&f_new_node);
190 fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
191 foreach_pset(set, entry) {
192 fprintf(dmp->f, "%-16s %8u %8u %8u\n",
193 get_id_str(entry->op->name),
194 cnt_to_uint(&entry->cnt_alive),
195 cnt_to_uint(&entry->new_node),
196 cnt_to_uint(&entry->into_Id)
199 cnt_add(&f_alive, &entry->cnt_alive);
200 cnt_add(&f_new_node, &entry->new_node);
201 cnt_add(&f_Id, &entry->into_Id);
203 fprintf(dmp->f, "-------------------------------------------\n");
204 fprintf(dmp->f, "%-16s %8u %8u %8u\n", "Sum",
205 cnt_to_uint(&f_alive),
206 cnt_to_uint(&f_new_node),
209 } /* simple_dump_opcode_hash */
212 * Return the name of an optimization.
214 static const char *get_opt_name(int index) {
215 assert(index < (int) ARR_SIZE(opt_names) && "index out of range");
216 assert((int) opt_names[index].kind == index && "opt_names broken");
217 return opt_names[index].name;
221 * dumps an optimization hash into human readable form
223 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
225 if (pset_count(set) > 0) {
227 const char *name = get_opt_name(index);
229 fprintf(dmp->f, "\n%s:\n", name);
230 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
232 foreach_pset(set, entry) {
233 fprintf(dmp->f, "%-16s %8u\n",
234 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
237 } /* simple_dump_opt_hash */
240 * dumps the register pressure for each block and for each register class
242 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
244 be_block_entry_t *b_entry = pset_first(entry->be_block_hash);
245 reg_pressure_entry_t *rp_entry;
247 /* return if no be statistic information available */
251 fprintf(dmp->f, "\nREG PRESSURE:\n");
252 fprintf(dmp->f, "%12s", "Block Nr");
254 /* print table head (register class names) */
255 foreach_pset(b_entry->reg_pressure, rp_entry)
256 fprintf(dmp->f, "%15s", rp_entry->class_name);
257 fprintf(dmp->f, "\n");
259 /* print the reg pressure for all blocks and register classes */
260 for (/* b_entry is already initialized */ ;
262 b_entry = pset_next(entry->be_block_hash)) {
263 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
265 foreach_pset(b_entry->reg_pressure, rp_entry)
266 fprintf(dmp->f, "%15d", rp_entry->pressure);
267 fprintf(dmp->f, "\n");
269 } /* simple_dump_be_block_reg_pressure */
271 /** prints a distribution entry */
272 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env) {
274 fprintf(dmp->f, "%12d", cnt_to_uint(&entry->cnt));
275 } /* simple_dump_distrib_entry */
278 * dumps the distribution of the amount of ready nodes for each block
280 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
282 if (pset_count(entry->be_block_hash) > 0) {
283 be_block_entry_t *b_entry;
286 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
287 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
288 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
290 foreach_pset(entry->be_block_hash, b_entry) {
291 /* this ensures that all keys from 1 to 5 are in the table */
292 for (i = 1; i < 6; ++i)
293 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
295 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
296 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
297 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
298 fprintf(dmp->f, "\n");
301 } /* simple_dump_be_block_sched_ready */
304 * Adds the counter for given entry to another distribution table.
306 static void add_distrib_entry(const distrib_entry_t *entry, void *env) {
307 distrib_tbl_t *sum_tbl = env;
309 stat_add_int_distrib_tbl(sum_tbl, PTR_TO_INT(entry->object), &entry->cnt);
310 } /* add_distrib_entry */
313 * dumps permutation statistics for one and block and one class
315 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
317 perm_stat_entry_t *ps_ent;
318 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
319 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
323 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
332 foreach_pset(entry->perm_stat, ps_ent) {
333 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
336 stat_get_count_distrib_tbl(ps_ent->chains),
337 stat_get_count_distrib_tbl(ps_ent->cycles),
342 /* sum up distribution table for chains */
343 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
345 /* sum up distribution table for cycles */
346 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
349 /* print chain distribution for all perms of this class in this block */
350 fprintf(dmp->f, "chain distribution:\n");
352 /* add all missing entries to chain distribution table */
353 for (i = 1; i <= entry->n_regs; i++) {
354 snprintf(buf, sizeof(buf), "length %d", i);
355 fprintf(dmp->f, "%12s", buf);
356 stat_insert_int_distrib_tbl(sum_chains, i);
358 fprintf(dmp->f, "\n");
359 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
360 fprintf(dmp->f, "\n");
362 /* print cycle distribution for all perms of this class in this block */
363 fprintf(dmp->f, "cycle distribution:\n");
365 /* add all missing entries to cycle distribution table */
366 for (i = 1; i <= entry->n_regs; i++) {
367 snprintf(buf, sizeof(buf), "length %d", i);
368 fprintf(dmp->f, "%12s", buf);
369 stat_insert_int_distrib_tbl(sum_cycles, i);
371 fprintf(dmp->f, "\n");
372 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
373 fprintf(dmp->f, "\n");
375 /* delete temporary sum distribution tables */
376 stat_delete_distrib_tbl(sum_chains);
377 stat_delete_distrib_tbl(sum_cycles);
379 } /* simple_dump_be_block_permstat_class */
382 * dumps statistics about perms
384 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
386 if (pset_count(entry->be_block_hash) > 0) {
387 be_block_entry_t *b_entry;
389 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
390 foreach_pset(entry->be_block_hash, b_entry) {
391 perm_class_entry_t *pc_ent;
393 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
395 if (b_entry->perm_class_stat) {
396 foreach_pset(b_entry->perm_class_stat, pc_ent) {
397 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
398 simple_dump_be_block_permstat_class(dmp, pc_ent);
403 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
405 } /* simple_dump_be_block_permstat */
408 * dumps the number of real_function_call optimization
410 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
415 if (! cnt_eq(cnt, 0)) {
416 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
417 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
419 } /* simple_dump_real_func_calls */
422 * dumps the number of tail_recursion optimization
424 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
429 if (num_tail_recursion > 0) {
430 fprintf(dmp->f, "\nTail recursion optimized:\n");
431 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
433 } /* simple_dump_tail_recursion */
436 * dumps the edges count
438 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
443 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
444 } /* simple_dump_edges */
449 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
451 int i, dump_opts = 1;
452 block_entry_t *b_entry;
453 extbb_entry_t *eb_entry;
459 ir_graph *const_irg = get_const_code_irg();
461 if (entry->irg == const_irg)
462 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
465 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
467 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
470 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
471 " was inlined : %u\n"
472 " got inlined : %u\n"
473 " strength red : %u\n"
474 " leaf function : %s\n"
475 " calls only leaf functions : %s\n"
479 " indirect calls : %u\n"
480 " external calls : %u\n",
481 entry->is_deleted ? "DELETED " : "",
482 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
483 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
484 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
485 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
486 entry->is_leaf ? "YES" : "NO",
487 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
488 entry->is_recursive ? "YES" : "NO",
489 entry->is_chain_call ? "YES" : "NO",
490 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
491 cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
492 cnt_to_uint(&entry->cnt[gcnt_external_calls])
495 for (i = 0; i < IF_RESULT_LAST; ++i) {
496 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
499 fprintf(dmp->f, "\nGlobals counts:\n");
500 fprintf(dmp->f, "--------------\n");
506 " pure address calc ops : %u\n"
507 " all address calc ops : %u\n",
508 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
509 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
512 /* Load/Store address classification */
514 " global Ld/St address : %u\n"
515 " local Ld/St address : %u\n"
516 " this Ld/St address : %u\n"
517 " param Ld/St address : %u\n"
518 " other Ld/St address : %u\n",
519 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
520 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
521 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
522 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
523 cnt_to_uint(&entry->cnt[gcnt_other_adr])
526 simple_dump_opcode_hash(dmp, entry->opcode_hash);
527 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
529 /* effects of optimizations */
533 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
534 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
536 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
537 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
540 /* dump block info */
541 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
542 foreach_pset(entry->block_hash, b_entry) {
543 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
545 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
546 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
547 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
548 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
549 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
550 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
551 b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
555 /* dump block reg pressure */
556 simple_dump_be_block_reg_pressure(dmp, entry);
558 /* dump block ready nodes distribution */
559 simple_dump_be_block_sched_ready(dmp, entry);
561 /* dump block permutation statistics */
562 simple_dump_be_block_permstat(dmp, entry);
564 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
565 /* dump extended block info */
566 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
567 foreach_pset(entry->extbb_hash, eb_entry) {
568 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
570 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
571 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
572 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
573 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
574 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
575 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
580 } /* simple_dump_graph */
583 * dumps the constant table
585 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
595 fprintf(dmp->f, "\nConstant Information:\n");
596 fprintf(dmp->f, "---------------------\n");
598 fprintf(dmp->f, "\nBit usage for integer constants\n");
599 fprintf(dmp->f, "-------------------------------\n");
601 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
602 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
603 cnt_add(&sum, &tbl->int_bits_count[i]);
605 fprintf(dmp->f, "-------------------------------\n");
607 fprintf(dmp->f, "\nFloating point constants classification\n");
608 fprintf(dmp->f, "--------------------------------------\n");
609 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
610 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
611 cnt_add(&sum, &tbl->floats[i]);
613 fprintf(dmp->f, "--------------------------------------\n");
615 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
616 cnt_add(&sum, &tbl->others);
617 fprintf(dmp->f, "-------------------------------\n");
619 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
620 } /* simple_dump_const_tbl */
623 * Dumps a line of the parameter table
625 static void dump_tbl_line(const distrib_entry_t *entry, void *env) {
628 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
629 } /* dump_tbl_line */
632 * dumps the parameter distribution table
634 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
635 fprintf(dmp->f, "\nCall parameter Information:\n");
636 fprintf(dmp->f, "---------------------\n");
638 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
639 fprintf(dmp->f, "-------------------------------\n");
641 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
642 fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
643 fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
644 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
645 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
646 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
647 } /* simple_dump_param_tbl */
650 * dumps the optimization counter table
652 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
655 fprintf(dmp->f, "\nOptimization counts:\n");
656 fprintf(dmp->f, "---------------------\n");
658 for (i = 0; i < len; ++i) {
659 unsigned cnt = cnt_to_uint(&tbl[i]);
662 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
665 } /* simple_dump_opt_cnt */
668 * initialize the simple dumper
670 static void simple_init(dumper_t *dmp, const char *name) {
673 snprintf(fname, sizeof(fname), "%s.txt", name);
674 dmp->f = fopen(fname, "w");
681 * finishes the simple dumper
683 static void simple_finish(dumper_t *dmp) {
687 } /* simple_finish */
690 * the simple human readable dumper
692 const dumper_t simple_dumper = {
694 simple_dump_const_tbl,
695 simple_dump_param_tbl,
703 FOURCC('S', 'M', 'P', 'L'),
706 /* ---------------------------------------------------------------------- */
709 * count the nodes as needed:
711 * 1 normal (data) Phi's
716 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
721 for (i = 0; i < 4; ++i)
724 foreach_pset(graph->opcode_hash, entry) {
725 if (entry->op == op_Phi) {
727 cnt_add(&cnt[1], &entry->cnt_alive);
728 } else if (entry->op == dmp->status->op_PhiM) {
730 cnt_add(&cnt[2], &entry->cnt_alive);
731 } else if (entry->op == op_Proj) {
733 cnt_add(&cnt[3], &entry->cnt_alive);
735 /* all other nodes */
736 cnt_add(&cnt[0], &entry->cnt_alive);
739 } /* csv_count_nodes */
744 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
752 if (entry->irg && !entry->is_deleted) {
753 ir_graph *const_irg = get_const_code_irg();
755 if (entry->irg == const_irg) {
756 name = "<Const code Irg>";
760 name = get_entity_name(entry->ent);
762 name = "<UNKNOWN IRG>";
765 csv_count_nodes(dmp, entry, cnt);
767 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
770 cnt_to_uint(&cnt[0]),
771 cnt_to_uint(&cnt[1]),
772 cnt_to_uint(&cnt[2]),
776 } /* csv_dump_graph */
781 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
786 } /* csv_dump_const_tbl */
789 * dumps the parameter distribution table
791 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
796 } /* csv_dump_param_tbl */
799 * dumps the optimization counter
801 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
806 } /* csv_dump_opt_cnt */
809 * initialize the simple dumper
811 static void csv_init(dumper_t *dmp, const char *name)
815 snprintf(fname, sizeof(fname), "%s.csv", name);
816 dmp->f = fopen(fname, "a");
822 * finishes the simple dumper
824 static void csv_finish(dumper_t *dmp)
832 * the simple human readable dumper
834 const dumper_t csv_dumper = {
845 FOURCC('C', 'S', 'V', '\0')