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_NOP, "the operation is a NOP" },
133 { FS_OPT_RTS_ABS, "RTS optimization: call to abs() replaced" },
134 { FS_OPT_RTS_ALLOCA, "RTS optimization: call to alloca() replaced" },
135 { FS_OPT_RTS_SQRT, "RTS optimization: call to sqrt() replaced" },
136 { FS_OPT_RTS_CBRT, "RTS optimization: call to cbrt() replaced" },
137 { FS_OPT_RTS_POW, "RTS optimization: call to pow() replaced" },
138 { FS_OPT_RTS_EXP, "RTS optimization: call to exp() replaced" },
139 { FS_OPT_RTS_LOG, "RTS optimization: call to log() replaced" },
140 { FS_OPT_RTS_SIN, "RTS optimization: call to sin() replaced" },
141 { FS_OPT_RTS_COS, "RTS optimization: call to cos() replaced" },
142 { FS_OPT_RTS_TAN, "RTS optimization: call to tan() replaced" },
143 { FS_OPT_RTS_ASIN, "RTS optimization: call to asin() replaced" },
144 { FS_OPT_RTS_ACOS, "RTS optimization: call to atan() replaced" },
145 { FS_OPT_RTS_ATAN, "RTS optimization: call to acos() replaced" },
146 { FS_OPT_RTS_SINH, "RTS optimization: call to sinh() replaced" },
147 { FS_OPT_RTS_COSH, "RTS optimization: call to cosh() replaced" },
148 { FS_OPT_RTS_TANH, "RTS optimization: call to tanh() replaced" },
149 { FS_OPT_RTS_SYMMETRIC, "RTS optimization: call to symmetric function f(-x) replaced by f(x)" },
150 { FS_OPT_RTS_STRCMP, "RTS optimization: call to strcmp() replaced" },
151 { FS_OPT_RTS_STRNCMP, "RTS optimization: call to strncmp() replaced" },
152 { FS_OPT_RTS_MEMCPY, "RTS optimization: call to memcpy() replaced" },
153 { FS_OPT_RTS_MEMSET, "RTS optimization: call to memset() replaced" },
154 { FS_OPT_RTS_STRLEN, "RTS optimization: call to strlen() replaced" },
155 { FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
156 { FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
157 { FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
158 { FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
159 { FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
160 { FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
161 { FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
162 { FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
163 { FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
164 { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
165 { FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
168 static const char *if_conv_names[IF_RESULT_LAST] = {
170 "if conv side effect ",
171 "if conv Phi node found ",
172 "if conv to deep DAG's ",
173 "if conv bad control flow ",
174 "if conv denied by arch ",
178 * dumps a opcode hash into human readable form
180 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
184 counter_t f_new_node;
188 cnt_clr(&f_new_node);
191 fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
192 foreach_pset(set, entry) {
193 fprintf(dmp->f, "%-16s %8u %8u %8u\n",
194 get_id_str(entry->op->name),
195 cnt_to_uint(&entry->cnt_alive),
196 cnt_to_uint(&entry->new_node),
197 cnt_to_uint(&entry->into_Id)
200 cnt_add(&f_alive, &entry->cnt_alive);
201 cnt_add(&f_new_node, &entry->new_node);
202 cnt_add(&f_Id, &entry->into_Id);
204 fprintf(dmp->f, "-------------------------------------------\n");
205 fprintf(dmp->f, "%-16s %8u %8u %8u\n", "Sum",
206 cnt_to_uint(&f_alive),
207 cnt_to_uint(&f_new_node),
210 } /* simple_dump_opcode_hash */
213 * Return the name of an optimization.
215 static const char *get_opt_name(int index) {
216 assert(index < (int) ARR_SIZE(opt_names) && "index out of range");
217 assert((int) opt_names[index].kind == index && "opt_names broken");
218 return opt_names[index].name;
222 * dumps an optimization hash into human readable form
224 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
226 if (pset_count(set) > 0) {
228 const char *name = get_opt_name(index);
230 fprintf(dmp->f, "\n%s:\n", name);
231 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
233 foreach_pset(set, entry) {
234 fprintf(dmp->f, "%-16s %8u\n",
235 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
238 } /* simple_dump_opt_hash */
241 * dumps the register pressure for each block and for each register class
243 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
245 be_block_entry_t *b_entry = pset_first(entry->be_block_hash);
246 reg_pressure_entry_t *rp_entry;
248 /* return if no be statistic information available */
252 fprintf(dmp->f, "\nREG PRESSURE:\n");
253 fprintf(dmp->f, "%12s", "Block Nr");
255 /* print table head (register class names) */
256 foreach_pset(b_entry->reg_pressure, rp_entry)
257 fprintf(dmp->f, "%15s", rp_entry->class_name);
258 fprintf(dmp->f, "\n");
260 /* print the reg pressure for all blocks and register classes */
261 for (/* b_entry is already initialized */ ;
263 b_entry = pset_next(entry->be_block_hash)) {
264 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
266 foreach_pset(b_entry->reg_pressure, rp_entry)
267 fprintf(dmp->f, "%15d", rp_entry->pressure);
268 fprintf(dmp->f, "\n");
270 } /* simple_dump_be_block_reg_pressure */
272 /** prints a distribution entry */
273 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env) {
275 fprintf(dmp->f, "%12d", cnt_to_uint(&entry->cnt));
276 } /* simple_dump_distrib_entry */
279 * dumps the distribution of the amount of ready nodes for each block
281 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
283 if (pset_count(entry->be_block_hash) > 0) {
284 be_block_entry_t *b_entry;
287 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
288 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
289 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
291 foreach_pset(entry->be_block_hash, b_entry) {
292 /* this ensures that all keys from 1 to 5 are in the table */
293 for (i = 1; i < 6; ++i)
294 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
296 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
297 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
298 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
299 fprintf(dmp->f, "\n");
302 } /* simple_dump_be_block_sched_ready */
305 * Adds the counter for given entry to another distribution table.
307 static void add_distrib_entry(const distrib_entry_t *entry, void *env) {
308 distrib_tbl_t *sum_tbl = env;
310 stat_add_int_distrib_tbl(sum_tbl, PTR_TO_INT(entry->object), &entry->cnt);
311 } /* add_distrib_entry */
314 * dumps permutation statistics for one and block and one class
316 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
318 perm_stat_entry_t *ps_ent;
319 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
320 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
324 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
333 foreach_pset(entry->perm_stat, ps_ent) {
334 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
337 stat_get_count_distrib_tbl(ps_ent->chains),
338 stat_get_count_distrib_tbl(ps_ent->cycles),
343 /* sum up distribution table for chains */
344 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
346 /* sum up distribution table for cycles */
347 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
350 /* print chain distribution for all perms of this class in this block */
351 fprintf(dmp->f, "chain distribution:\n");
353 /* add all missing entries to chain distribution table */
354 for (i = 1; i <= entry->n_regs; i++) {
355 snprintf(buf, sizeof(buf), "length %d", i);
356 fprintf(dmp->f, "%12s", buf);
357 stat_insert_int_distrib_tbl(sum_chains, i);
359 fprintf(dmp->f, "\n");
360 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
361 fprintf(dmp->f, "\n");
363 /* print cycle distribution for all perms of this class in this block */
364 fprintf(dmp->f, "cycle distribution:\n");
366 /* add all missing entries to cycle distribution table */
367 for (i = 1; i <= entry->n_regs; i++) {
368 snprintf(buf, sizeof(buf), "length %d", i);
369 fprintf(dmp->f, "%12s", buf);
370 stat_insert_int_distrib_tbl(sum_cycles, i);
372 fprintf(dmp->f, "\n");
373 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
374 fprintf(dmp->f, "\n");
376 /* delete temporary sum distribution tables */
377 stat_delete_distrib_tbl(sum_chains);
378 stat_delete_distrib_tbl(sum_cycles);
380 } /* simple_dump_be_block_permstat_class */
383 * dumps statistics about perms
385 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
387 if (pset_count(entry->be_block_hash) > 0) {
388 be_block_entry_t *b_entry;
390 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
391 foreach_pset(entry->be_block_hash, b_entry) {
392 perm_class_entry_t *pc_ent;
394 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
396 if (b_entry->perm_class_stat) {
397 foreach_pset(b_entry->perm_class_stat, pc_ent) {
398 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
399 simple_dump_be_block_permstat_class(dmp, pc_ent);
404 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
406 } /* simple_dump_be_block_permstat */
409 * dumps the number of real_function_call optimization
411 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
416 if (! cnt_eq(cnt, 0)) {
417 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
418 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
420 } /* simple_dump_real_func_calls */
423 * dumps the number of tail_recursion optimization
425 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
430 if (num_tail_recursion > 0) {
431 fprintf(dmp->f, "\nTail recursion optimized:\n");
432 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
434 } /* simple_dump_tail_recursion */
437 * dumps the edges count
439 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
444 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
445 } /* simple_dump_edges */
450 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
452 int i, dump_opts = 1;
453 block_entry_t *b_entry;
454 extbb_entry_t *eb_entry;
460 ir_graph *const_irg = get_const_code_irg();
462 if (entry->irg == const_irg)
463 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
466 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
468 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
471 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
472 " was inlined : %u\n"
473 " got inlined : %u\n"
474 " strength red : %u\n"
475 " leaf function : %s\n"
476 " calls only leaf functions : %s\n"
480 " indirect calls : %u\n"
481 " external calls : %u\n",
482 entry->is_deleted ? "DELETED " : "",
483 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
484 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
485 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
486 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
487 entry->is_leaf ? "YES" : "NO",
488 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
489 entry->is_recursive ? "YES" : "NO",
490 entry->is_chain_call ? "YES" : "NO",
491 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
492 cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
493 cnt_to_uint(&entry->cnt[gcnt_external_calls])
496 for (i = 0; i < IF_RESULT_LAST; ++i) {
497 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
500 fprintf(dmp->f, "\nGlobals counts:\n");
501 fprintf(dmp->f, "--------------\n");
507 " pure address calc ops : %u\n"
508 " all address calc ops : %u\n",
509 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
510 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
513 /* Load/Store address classification */
515 " global Ld/St address : %u\n"
516 " local Ld/St address : %u\n"
517 " this Ld/St address : %u\n"
518 " param Ld/St address : %u\n"
519 " other Ld/St address : %u\n",
520 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
521 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
522 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
523 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
524 cnt_to_uint(&entry->cnt[gcnt_other_adr])
527 simple_dump_opcode_hash(dmp, entry->opcode_hash);
528 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
530 /* effects of optimizations */
534 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
535 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
537 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
538 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
541 /* dump block info */
542 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
543 foreach_pset(entry->block_hash, b_entry) {
544 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
546 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
547 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
548 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
549 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
550 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
551 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
552 b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
556 /* dump block reg pressure */
557 simple_dump_be_block_reg_pressure(dmp, entry);
559 /* dump block ready nodes distribution */
560 simple_dump_be_block_sched_ready(dmp, entry);
562 /* dump block permutation statistics */
563 simple_dump_be_block_permstat(dmp, entry);
565 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
566 /* dump extended block info */
567 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
568 foreach_pset(entry->extbb_hash, eb_entry) {
569 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
571 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
572 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
573 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
574 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
575 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
576 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
581 } /* simple_dump_graph */
584 * dumps the constant table
586 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
596 fprintf(dmp->f, "\nConstant Information:\n");
597 fprintf(dmp->f, "---------------------\n");
599 fprintf(dmp->f, "\nBit usage for integer constants\n");
600 fprintf(dmp->f, "-------------------------------\n");
602 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
603 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
604 cnt_add(&sum, &tbl->int_bits_count[i]);
606 fprintf(dmp->f, "-------------------------------\n");
608 fprintf(dmp->f, "\nFloating point constants classification\n");
609 fprintf(dmp->f, "--------------------------------------\n");
610 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
611 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
612 cnt_add(&sum, &tbl->floats[i]);
614 fprintf(dmp->f, "--------------------------------------\n");
616 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
617 cnt_add(&sum, &tbl->others);
618 fprintf(dmp->f, "-------------------------------\n");
620 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
621 } /* simple_dump_const_tbl */
624 * Dumps a line of the parameter table
626 static void dump_tbl_line(const distrib_entry_t *entry, void *env) {
629 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
630 } /* dump_tbl_line */
633 * dumps the parameter distribution table
635 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
636 fprintf(dmp->f, "\nCall parameter Information:\n");
637 fprintf(dmp->f, "---------------------\n");
639 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
640 fprintf(dmp->f, "-------------------------------\n");
642 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
643 fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
644 fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
645 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
646 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
647 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
648 } /* simple_dump_param_tbl */
651 * dumps the optimization counter table
653 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
656 fprintf(dmp->f, "\nOptimization counts:\n");
657 fprintf(dmp->f, "---------------------\n");
659 for (i = 0; i < len; ++i) {
660 unsigned cnt = cnt_to_uint(&tbl[i]);
663 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
666 } /* simple_dump_opt_cnt */
669 * initialize the simple dumper
671 static void simple_init(dumper_t *dmp, const char *name) {
674 snprintf(fname, sizeof(fname), "%s.txt", name);
675 dmp->f = fopen(fname, "w");
682 * finishes the simple dumper
684 static void simple_finish(dumper_t *dmp) {
688 } /* simple_finish */
691 * the simple human readable dumper
693 const dumper_t simple_dumper = {
695 simple_dump_const_tbl,
696 simple_dump_param_tbl,
704 FOURCC('S', 'M', 'P', 'L'),
707 /* ---------------------------------------------------------------------- */
710 * count the nodes as needed:
712 * 1 normal (data) Phi's
717 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
722 for (i = 0; i < 4; ++i)
725 foreach_pset(graph->opcode_hash, entry) {
726 if (entry->op == op_Phi) {
728 cnt_add(&cnt[1], &entry->cnt_alive);
729 } else if (entry->op == dmp->status->op_PhiM) {
731 cnt_add(&cnt[2], &entry->cnt_alive);
732 } else if (entry->op == op_Proj) {
734 cnt_add(&cnt[3], &entry->cnt_alive);
736 /* all other nodes */
737 cnt_add(&cnt[0], &entry->cnt_alive);
740 } /* csv_count_nodes */
745 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
753 if (entry->irg && !entry->is_deleted) {
754 ir_graph *const_irg = get_const_code_irg();
756 if (entry->irg == const_irg) {
757 name = "<Const code Irg>";
761 name = get_entity_name(entry->ent);
763 name = "<UNKNOWN IRG>";
766 csv_count_nodes(dmp, entry, cnt);
768 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
771 cnt_to_uint(&cnt[0]),
772 cnt_to_uint(&cnt[1]),
773 cnt_to_uint(&cnt[2]),
777 } /* csv_dump_graph */
782 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
787 } /* csv_dump_const_tbl */
790 * dumps the parameter distribution table
792 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
797 } /* csv_dump_param_tbl */
800 * dumps the optimization counter
802 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
807 } /* csv_dump_opt_cnt */
810 * initialize the simple dumper
812 static void csv_init(dumper_t *dmp, const char *name)
816 snprintf(fname, sizeof(fname), "%s.csv", name);
817 dmp->f = fopen(fname, "a");
823 * finishes the simple dumper
825 static void csv_finish(dumper_t *dmp)
833 * the simple human readable dumper
835 const dumper_t csv_dumper = {
846 FOURCC('C', 'S', 'V', '\0')